Auto Selecting the next Input field and going Back - javascript

Once inputed, a user can't go back to change their input.
$("form").on("keyup change paste", function(e) {
e.preventDefault();
var a = $(this).find("input[type='text'].a");
var b = $(this).find("input[type='text'].b");
var c = $(this).find("input[type='text'].c");
var d = $(this).find("input[type='text'].d");
var e = $(this).find("input[type='text'].e");
var f = $(this).find("input[type='text'].f");
a.val(a.val().replace(/[^0-9]/g, ""));
b.val(b.val().replace(/[^0-9]/g, ""));
c.val(c.val().replace(/[^0-9]/g, ""));
d.val(d.val().replace(/[^0-9]/g, ""));
e.val(e.val().replace(/[^0-9]/g, ""));
f.val(f.val().replace(/[^0-9]/g, ""));
if (a.val().length == a.attr('maxlength')) {
a.next("input").focus();
}
if (b.val().length == a.attr('maxlength')) {
b.next("input").focus();
}
if (c.val().length == a.attr('maxlength')) {
c.next().next("input").focus();
}
if (d.val().length == a.attr('maxlength')) {
d.next("input").focus();
}
if (e.val().length == a.attr('maxlength')) {
e.next("input").focus();
}
if (f.val().length == a.attr('maxlength')) {
f.next("input").focus();
}
});
input {
width: 20px;
text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form name="code" action="*" method="post" autocomplete="off">
<input type="text" name="code" maxlength="1" autocomplete="off" class="a">
<input type="text" name="code" maxlength="1" autocomplete="off" class="b">
<input type="text" name="code" maxlength="1" autocomplete="off" class="c">
<span>—</span>
<input type="text" name="code" maxlength="1" autocomplete="off" class="d">
<input type="text" name="code" maxlength="1" autocomplete="off" class="e">
<input type="text" name="code" maxlength="1" autocomplete="off" class="f last">
</form>
How can that be done?
And is there a more elegant approach to mine above?
Live: jsFiddle

Any time you find yourself finding very repetitious code, always think LOOP.
The below will allow the user to edit their values. It also greatly reduces your code.
$('form').on('input', e => {
var letters = ['a', 'b', 'c', 'd', 'e', 'f'];
letters.forEach(letter => {
let field = $(e.target);
field.val(field.val().replace(/[^0-9]/g, ''));
if(field.val().length == field.attr('maxlength')) { field.nextAll('input').first().focus(); }
});
});
Fiddle.
Notes:
Listen for the input event; it has the advantage of covering all the events you were listening for, and, crucially, fires after keypress (meaning you can be sure of grabbing the latest, complete value from the field)
avoid repetitious code; the loop allows us to write the business logic once rather than repeatedly
there is no need to prevent the event's default action
by using nextAll('input').first(), we can be sure of getting the next input, whether it's the next sibling or, as is the case with the third input, separated by another type of element

My idea would be to focus next, and loop when arriving at the last one. Replace the number in case of a new entry.
// init the html
const nbInput = 6;
let html = '';
for (let i = 0; i < nbInput; i += 1) {
html += `<input type="text" name="code" maxlength="1" autocomplete="off" number="${i}">`;
}
$('form').html(html);
$('form input').on('keypress', function(e) {
e.preventDefault();
// Ignore bad values
if (/^[^0-9]$/g.test(String.fromCharCode(e.which))) {
return;
}
// Replace the actual value with the keypressed one
$(this).val(String.fromCharCode(e.which));
// Reset & focus next
if ($(this).val() !== '' && Number($(this).attr('number')) < (nbInput - 1)) {
$(`input[number=${Number($(this).attr('number')) + 1}]`).focus();
} else {
// Focus the first item when we finished
$('input[number="0"]').focus();
}
});
input {
width: 20px;
text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form name="code" action="*" method="post" autocomplete="off">
</form>

Clearing the inputs on focus would do it. (I don't use jQuery much, so apologies if I have any incorrect syntax.)
$("form").focus(function() {
var a = $(this).find("input[type='text'].a")
var b = $(this).find("input[type='text'].b") // ...etc
a.val("");
b.val(""); // ...etc
});
That said, Utkanos is 100% correct that a loop is the right way to handle both issues (auto-advancing and allowing edits).

Related

jQuery check if one of the inputs with same class is not empty

I'm having two elements with same classname and I am doing $(".text-input") to select all of them. In the on input callback,
$(".text-input").on("input", function (event) {
console.log(is any of those not empty?);
})
in of any one of these, I want to know if at least one of the input boxes are not empty. How do I do this?
Actually, you shoulld always .trim() the content before testing.
You don't want whitespaces to account for a valid input value:
$(".text-input").on("input", function() {
const is_empty = !this.value.trim();
if (is_empty) console.log("field is empty");
$(this).toggleClass("is-empty", is_empty);
});
/* bool helpers */
.is-empty {
outline: 2px solid red;
outline-offset: -2px;
}
<input type="text" class="text-input">
<input type="text" class="text-input">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
To answer your second question:
"I want to know if at least one of the input boxes are not empty. How do I do this?"
Use Array.prototype.some()
// Return true if at least one input has value
const atLeastOneNotEmpty = (elements) => {
return [...elements].some(el => el.value.trim());
}
Example code
const $inp = $(".text-input");
const validateEmpty = () => {
$inp.each((i, el) => {
const is_empty = !el.value.trim();
if (is_empty) console.log(`field ${el.name} is empty`);
el.classList.toggle("is-empty", is_empty);
});
};
// Return true if at least one input has value
const atLeastOneNotEmpty = (ELs) => [...ELs].some(el => el.value.trim());
$inp.on('input', validateEmpty);
$("#test").on("click", () => {
console.log(atLeastOneNotEmpty(jQuery.makeArray($inp)))
});
/* bool helpers */
.is-empty {
outline: 2px solid red;
outline-offset: -2px;
}
<input type="text" class="text-input" name="a"><br>
<input type="text" class="text-input" name="b" value="foo"><br>
<input type="text" class="text-input" name="c"><br>
<button id="test" type="button">TEST one has value</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
You can check the content of all text-input elements in with the each() method. With not(this) you can exclude the currently typed into textbox.
$('.text-input').on('input change', function() {
// check all elements with the 'text-input class', but exclude the one currrently typed into
$('.text-input').not(this).each(function(){
// if there is content in one of the others, then display a message in console
if($(this).val().trim().length > 0) {
// one of the inputs already has something in it
console.log('Something is filled in another box');
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" class="text-input" />
<input type="text" class="text-input" />
<input type="text" class="text-input" />
One way is use filter() to create a collection of the ones that have values and then compare length of that collection to length of all the inputs
const $inputs = $('.text-input').on('input', function() {
const $filled = $inputs.filter((_, el) => !!el.value.trim());
console.clear();
if ( $filled.length < $inputs.length ) {
console.log('At least one is empty')
} else {
console.log('No empties')
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" class="text-input" />
<input type="text" class="text-input" />
<input type="text" class="text-input" />
You can just check if the length of the value of each input is equal to 0. If it is then do whatever you want.
Here is the code.
$(".text-input").on("input", function (event) {
if($(this).val().length == 0){
console.log("is any of those not empty?");
}
});

Array.foreach only gets val() from the last input id with keyup

Please help me figure out why only the last input id gets its value added to the input id= #attr3 with keyup.
I need both inputs in the div to have their values put into the input outside the div separated with a comma(,). i made a fiddle https://jsfiddle.net/dc6v6gjd/1/. Thanks
<div id ="candy">
<input type="text" id="attr1" name="emailAddress" value="">
<input type="text" id="attr2" name="emailAddress" value="">
</div>
<input type="text" id="attr3" name="username" value="">
$(document).ready(function () {
var text = $("#candy :input").map(function () {
return this.id;
}).get();
var attr = [];
for (i=0; i<text.length; i++) {
attr.push('#'+ text[i]);
}
var mat = attr.join(", ");
$(mat).keyup(function(){
update();
function update() {
attr.forEach(function(index, i){
// alert(i);
$("#attr3").val( $(attr[i]).val() + "," );
});
}
});
});
The reason is you're overriding the value of attr3 on each iteration of forEach. You could instead use join to get the value.
e.g.
function update() {
var val = attr
.map(function(a) {
return $(a).val();
})
.join(",");
$("#attr3").val(val);
}
That being said I'd probably go with a simpler solution like this.
// set the keyup event handler and add all inputs to an array.
var inputs = $("#candy :input").keyup(function() {
update();
}).get();
// read all input values into comma separated string and update attr3
function update() {
var val = inputs.map(function(i) {
return $(i).val();
}).join(",");
$("#attr3").val(val);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="candy">
<input type="text" id="attr1" name="emailAddress" value="">
<input type="text" id="attr2" name="emailAddress" value="">
</div>
<input type="text" id="attr3" name="username" value="">
Update: Support dynamically added inputs.
$(document).on("keyup", "#candy :input", function() {
update();
});
function update() {
var val = $("#candy :input").get().map(function(i) {
return $(i).val();
}).join(",");
$("#attrFinal").val(val);
}
var count = 3;
$("#add").click(function() {
$("#candy").append("<input type='text' id='attr" + count++ + "' name='emailAddress' />");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="candy">
<input type="text" id="attr1" name="emailAddress" value="">
<input type="text" id="attr2" name="emailAddress" value="">
</div>
<input type="text" id="attrFinal" name="username" value="">
<button id="add">Add New</button>

Input tag type number for credit card

I have 4 input tags.
<input type="number" class="br1" name="first">
<input type="number" class="br1" name="secound">
<input type="number" class="br1" name="third">
<input type="number" class="br1" name="fourth">
I want to set maxlength (4 numbers) for every input tag. I tried to set maxlength but it doesn't work. Also, when I enter 4 numbers in one input tag, I want to automaticlly input in next input tag.
Thanks.
If you want to use maxlength change type of input to text. Then you can parse all you your inputs strings to a number.
$(".br1").keyup(function () {
if (this.value.length == this.maxLength) {
var $next = $(this).next('.br1');
if ($next.length)
$(this).next('.br1').focus();
else
$(this).blur();
}
});
$(".btn").click(function() {
var string = "";
$(".br1").each(function() {
string += this.value;
});
number = parseInt(string);
console.log(number);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" class="br1" name="first" maxlength=4>
<input type="text" class="br1" name="secound" maxlength=4>
<input type="text" class="br1" name="third" maxlength=4>
<input type="text" class="br1" name="fourth" maxlength=4>
<button class="btn">toNumber</button>
Use max="9999" and min="0000" to set the maximum value for input type number.
As per http://w3c.github.io/html/sec-forms.html#the-maxlength-and-minlength-attributes maxlength is not valid for input of type number.
You can use input event attached to .br1 elements, .slice() with parameters 0, -1 to remove character if .length of .value is greater than 4
var inputs = document.querySelectorAll(".br1");
for (let input of inputs) {
input.oninput = () => {
if (input.value.length > 4) {
input.value = input.value.slice(0, -1)
}
}
}
<input type="number" class="br1" name="first">
<input type="number" class="br1" name="secound">
<input type="number" class="br1" name="third">
<input type="number" class="br1" name="fourth">
You can do this using only javascript. Also note the maxLength attribute don't work on number, so you may need to use input type='text'
Here is snippet
// get the input
var inputBox = document.getElementsByClassName("br1")
// loop through the array of input
for (var i = 0; i < inputBox.length; i++) {
// creating a closure
(function(x) {
// adding event listener to each of the input
inputBox[x].addEventListener('keydown', function(x) {
// checking value of maxLength
var maxLength = parseInt(this.attributes["maxlength"].value, 10);
// length of the input value
var myLength = this.value.length;
// if both are equal then find the next sibling
if (myLength >= maxLength) {
var next = this.nextElementSibling
// if the next sibling is input, set focus to it
if (next.tagName.toLowerCase() === "input") {
next.focus();
}
}
})
}(i))
}
It as simple as posible, Try this:
$("input[type=number]").keypress(function (e) {
var el = $(this);
var currentValue = el.val();
var char = String.fromCharCode(e.keyCode || e.which);
if (currentValue.length === 3) {
el.val(currentValue + char);
e.preventDefault();
el.next().focus();
} else if (currentValue.length >= 4) {
e.preventDefault();
}
})
input[type=number]{
width:60px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<input type="number" class="br1" name="first">
<input type="number" class="br2" name="first">
<input type="number" class="br3" name="first">
<input type="number" class="br4" name="first">

Getting values from multiple text boxes on keypress in javascript

I have 8 different text fields in my form, it's a part of customer bill.
Here it is
<input type="text" name="txtcustomduty" class="form-control" placeholder="Customs Duty">
<input type="text" name="txtlcltranspotation" class="form-control" placeholder="Local Transportation">
......
up to 8
From this I want to show the sum of all the values as total value
<span>Total extra cost:1678</span>
It should be changed when the values of any text field is changed, so how can I do it perfectly using keyup event?
UPDATE
I have attached an onkeyup event to each textfield
`onkeyup="findSum(this.value)"'
and i am using a global array for store the input values var extras=[]
function findSum(value)
{
if(value!=''){
console.log(value);
extras.push(parseInt(value));
if(extras!='')
$('#extratotal').text(extras.reduce(getSum));
else $('#extratotal').text('0');
}
}
But its not worked well
You can get SUM of all inputs that have form-control class on keyup event like this:
$('input.form-control').on('keyup',function() {
var total = 0;
$('input.form-control').each(function(){
if (this.value == ''){
total += parseInt(0);
}else{
total += parseInt(this.value);
}
});
$('#total').val(total);
});
input {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" name="txtcustomduty" class="form-control" placeholder="Customs Duty" >
<input type="text" name="txtlcltranspotation" class="form-control" placeholder="Local Transportation" >
<input type="text" name="other" class="form-control" placeholder="other" >
Total extra cost: <input id="total" >
You can use the target.value property of the event passed to the key listener - this will give you the value of the input field:
document.addEventListener('input', 'keyup', function(e) {
// use e.target.value here
}
Just add this to a running total and update the text inside the listener function.
I have defined in JavaScript instead of jQuery. Try it..
<script>
function sum()
{
var sum = 0;
var array_field = document.getElementsByClassName('sum_field');
for(var i=0; i<array_field.length; i++)
{
var value = Number(array_field[i].value);
if (!isNaN(value)) sum += value;
}
document.getElementById("total").innerHTML = sum;
}
</script>
<body>
<input type="text" name="txtcustomduty" class="form-control sum_field" placeholder="Customs Duty" onkeyup="sum()">
<input type="text" name="txtlcltranspotation" class="form-control sum_field" placeholder="Local Transportation" onkeyup="sum()">
<p>Total:<span id="total">0</span></p>
</body>

ie8 update value event

I have been staring at this for 2 hours. The purpose is for when a user tabs out of a field, the value will be converted in to two digits.
For some reason IE8 Chokes on this the first time you try it but it works the second time. After that it occasionally breaks.
// backbone snippit
events: {
'blur [name=month], [name=day], [name=year]': 'sanitizeAge'
},
'sanitizeAge': function(e) {
var view = this;
var $el = $(e.target);
var $val = $el.val();
if($val.length === 1){
$el.val('0'+$val);
}
},
// html snippet
<div class="padded grid-quarter">
<input name="month" type="text" placeholder="MM" class="grid-whole text-field month" data-validate="month" data-min="2" maxlength="2" tabindex="3">
</div>
<div class="padded grid-quarter">
<input name="day" type="text" placeholder="DD" class="grid-whole text-field day" data-validate="day" data-min="2" maxlength="2" tabindex="4">
</div>
<div class="padded grid-half">
<input name="year" type="text" placeholder="Year of Birth" class="text-field grid-whole year" data-validate="year" data-min="4" maxlength="4" tabindex="5">
</div>
</fieldset>
Here's a simplified version of your answer:
'sanitizeAge': function(e) {
var val = e.target.value;
if (val.length === 1){
e.target.value = '0'+val;
}
},
I was able to get it to work only by getting the value via javascript instead of jquery.
'sanitizeAge': function(e) {
var view = this;
var $el = $(e.target);
var $val = $el[0].value; // <---- FIX
if($val.length === 1){
$el.val('0'+$val);
}
},

Categories