i have multiple input number fields with the same class, and i have to sum them but when I try with my javascript i get always NaN result
var arrNumber = new Array(); //contain the number of specific input field
var totale;
$(".input-n-pro").bind('keyup mouseup', function () {
totale = 0;
$('.input-n-pro').each(function(){
var this_num = $(this).val();
totale = parseInt(this_num)+parseInt(totale);
})
console.log("totale="+totale);
});
The html of input is this, generated by php, one for every row of a table
<input type="number" name="<?php echo $data["name"];?>" min="0" max="500" placeholder="0" class="form-control input-xs input-n-pro" style="display: inline">
I don't know it won't work, it work with only js withous jquery but i have to get the id of every field to do that and i want to do that for everyone with the same class because they are dinamic fields
P.S. The other part of my work, is to get every name of those fields and store them so i can have an array in js where i have the name of input and his number value, but i don't know how to do because they are dinamic
You probably parsing something that is not an integer. Then the parseInt won't work and returns NaN. If you sum a NaN, then it stays a NaN, example:
// working testcase:
const testArray = ['2', '3', '4'];
let total = 0;
for (value of testArray) {
total += parseInt(value);
}
// returns 9
console.log(total);
// your testcase:
const testArray2 = ['2', '3', 'notANumber'];
let total2 = 0;
for (value of testArray2) {
total2 += parseInt(value);
}
// returns NaN since we are adding 2 + 3 + NaN = NaN
console.log(total2);
So the solution is to 'negate' the NaN by treating it as 0:
// solution:
const myArray = ['2', '3', 'notANumber', '4'];
let total = 0;
for (value of myArray) {
// treat NaN, undefined or any falsey values as 0.
total += parseInt(value) || 0;
}
// returns 9
console.log(total);
To integrate this concept in your code, you'll get something like:
let total = 0;
$('.input-n-pro').each(() => {
let valueInString = $(this).val();
let actualValue = parseInt(valueInString) || 0;
total += actualValue;
});
if one of inputs value is empty then parseInt returns NAN. So you can better do a check using IsNan function. if input is empty than assign 0. For example;
var x= parseInt($('#abc').val()); if (isNaN(x)) x = 0;
Part 1 and 2 of your question
The reason you get NaN is most probably that if any of the inputs has no value, asking for that value returns an empty string (form fields always return strings) "". parseInt("") returns NaN.
Using vanilla ECMAScript 6, the solution is a one-liner with the help of Array.prototype.reduce:
const sum = [...document.querySelectorAll('.input-n-pro')].reduce((acc, val) => acc += Number(val.value) || 0, 0);
For your second question, just use Array.prototype.map. Also a one-liner.
const theArr = [...document.querySelectorAll('.input-n-pro')].map(x => {return { name: x.name, value: parseInt(x.value) || 0 }});
Note: The Array spread operator [...document.querySelectorAll('.input-n-pro')] makes an array from the NodeList document.querySelectorAll returns, so you can use Array methods on the list (like reduce and map).
Example:
calc.addEventListener('click', () => {
const sum = [...document.querySelectorAll('.input-n-pro')].reduce((acc, val) => acc += Number(val.value) || 0, 0);
console.log(sum);
})
getArr.addEventListener('click', () => {
const theArr = [...document.querySelectorAll('.input-n-pro')].map(x => {return { name: x.name, value: parseInt(x.value) || 0 }});
console.log(theArr);
})
<input type="number" value="5" class="input-n-pro" name="a" />
<input type="number" value="3" class="input-n-pro" name="b" />
<!-- lets insert one input that contains no number -->
<input type="text" value="foo" class="input-n-pro" name="m" />
<input type="number" value="2" class="input-n-pro" name="c" />
<input type="number" value="11" class="input-n-pro" name="d" />
<input type="number" class="input-n-pro" name="e" />
<br />
<button id="calc" type="button">Calculate Sum</button>
<button id="getArr" type="button">Get Array of name-value pairs</button>
bind() has been deprecated => use on
arrNumber = [], //contain the number of specific input field
totale = 0;
doTotale(); // first round
$(".input-n-pro").on('keyup mouseup change', doTotale);
function doTotale()
{
totale = 0;
arrNumber.length = 0;
$('.input-n-pro').each(function()
{
let
name = $(this).attr('name'),
val = parseInt($(this).val(),10) || 0;
arrNumber.push( {name, val });
totale += val;
})
console.clear();
console.log("totale =",totale);
console.log("arrNumber =", JSON.stringify(arrNumber) );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
AA : <input type="number" name="AA" value="5" class="input-n-pro" /> <br>
BB : <input type="number" name="BB" value="3" class="input-n-pro" /> <br>
CC : <input type="text" name="CC" value="foo" class="input-n-pro" /> <br> <!-- lets insert one input that contains no number -->
DD : <input type="number" name="DD" value="2" class="input-n-pro" /> <br>
EE : <input type="number" name="EE" value="11" class="input-n-pro" /> <br>
FF : <input type="number" name="FF" class="input-n-pro" />
Related
I have an input and I need it to be limited to only these values:
Min: 0.01 max 999.99
If I use maxlength="6" I can enter, for instance, 999.99 but also 1000.1 which is not an accepted value.
What I've tried:
1st attempt (not working):
<input type="number" id="quantity" name="quantity" maxlength="6" min="0.01" max="999.99">
2nd attempt (partially working):
let maximumFractionDigits = 2;
const formatNumber = (value) => {
return parseFloat(value.replace(/,/g,'')).toLocaleString('en-US', { maximumFractionDigits });
}
$('input[name="test"]').on('keyup',function(){
maximumFractionDigits = 2;
if (!$(this).val() || (maximumFractionDigits && $(this).val().endsWith('.'))) {
return
}
$(this).val(formatNumber($(this).val()).replace(/,/g,''));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
INPUT TEST
<input type="text" maxlength="6" name="test" class="form-control">
<br>
With the second approach, I still can input weird numbers like 10000. and values like 0.0X can't be introduced (I guess it's rounded), how could I just limit the values to Min: 0.01 max 999.99?
You can check for 3 conditions,
For first 2 convert number to string
The max length of the string should be 6
maxlength = 6
If string has decimal point then .split('.') and check the length of decimal numbers
const decimal = input.split('.')[1]
Check if the number is
0.01 < number < 999.99
You have to methods to achieve the same
change the input type, and set min-max values:
<input type="number" min=0.01 max=999.99 name="test" class="form-control" aria-label="Equipment Procurement %">
If you don't want to change the type:
const numInput = document.querySelector(".form-control");
numInput.addEventListener("input", (event) => {
const number = parseInt(e.target.value);
if (number > 999.99 && number < 0.01) // throw Error or do whatever you want to do
})
So basically I found a solution:
const input = document.querySelector('.example');
input.addEventListener('input', updateValue);
function updateValue(e) {
let number = e.target.value;
number = number.toString();
if(number.match(/^\d{1,3}(\.\d{1,2})?$/)){
console.log("True");
} else{
const newNum = (e.target.value).toString().slice(0, -1)
e.target.value = parseFloat(newNum);
}
}
<input type="number" class="form-control example" id="quantity" name="quantity" maxlength="6" min=0.01 max=999.99>
Hope this helps if someone has the same situation
I am creating an array sort number program where the user enters an array of numbers and clicking the Sort button will sort the numbers into numerical numbers. What I am wondering is how to get my program to ignore non-numbers? And how to set it to 1 number each line instead of putting them all on the same line?
var myarr = [];
function addTo() {
myarr.push(document.getElementById("userinput").value);
console.log(myarr); //to confirm it has been added to the array
};
function sortNumbers() {
myarr.sort(function(a, b){return a - b});
document.getElementById("userinput").append = myarr;
console.log(myarr);
}
<input type="number" id="userinput" />
<input type ="button" onclick="addTo()" value="Add Number" />
<button onclick="sortNumbers()">Sort</button>
Do you mean this?
var myarr = [];
function addTo() {
let n =document.getElementById("userinput").value;
myarr.push(n);
document.getElementById("inputA").innerText = myarr.toString();
};
function sortNumbers() {
myarr.sort(function(a, b) {return a - b});
;
let sortedB = document.getElementById("sortedB");
document.getElementById("sorted").innerText = myarr.toString();
sortedB.innerHTML = "";
myarr.forEach(n => sortedB.innerHTML += "<br/>" + n);
}
<input type="number" id="userinput" />
<input type ="button" onclick="addTo()" value="Add Number" />
<button onclick="sortNumbers()">Sort</button>
<p>Input array: <span id="inputA"></span></p>
<p>Sorted on one line: <span id="sorted"></span>
<br/>
Sorted on different lines: <span id="sortedB"></span>
</p>
I'm trying to count the number of common letters between the user's input and the number generated. I am counting it so that the placement doesn't matter between them (so 411 and 004 should say "1 number in common").
I've placed my code in a snippet below. It works fine, except for that, when the generated string has two of the same numbers, it doesn't work properly. You can see that by typing "4", it will say that there are two chars. in common, when there is really only one (it counts the four twice.)
So, after all this, I'm asking what is the best way to show the common letters between the input and the generated number?
I'm fine with using jQuery and/or JavaScript, and sorry if my code isn't very good, I'm not very advanced at all.
Thanks for any help in advance! :)
// on ".check" click...
$(".check").click(function() {
var nmb = $(".number").text();
var ltr = $(".input").val();
var count = $(".cnt");
// Set logged text to 0
count.text("0");
// Test for numbers in common
if (ltr.includes(nmb.charAt(0))) {
count.html(function(i, val) {
return val * 1 + 1
});
}
if (ltr.includes(nmb.charAt(1))) {
count.html(function(i, val) {
return val * 1 + 1
});
}
if (ltr.includes(nmb.charAt(2))) {
count.html(function(i, val) {
return val * 1 + 1
});
}
if (ltr.includes(nmb.charAt(3))) {
count.html(function(i, val) {
return val * 1 + 1
});
}
$(".res1").html(" numbers in common");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Generated Number: <span class="number">4410</span><br><br>
<input type="text" class="input" placeholder="Try typing 4 to see the issue" maxlength="4">
<input class="check" type="submit" value="CHECK">
<br><br>
<span id="full_res">
<span class="cnt"></span>
<span class="res1"></span>
</span>
First you can reduce each of the strings to only include unique characters, ie 4410 can be reduced to 410 as you don't need to test 4 more than once. You can do this by creating a Set of each string:
var numberSet = new Set(nmb);
var inputSet = new Set(ltr);
Then you can iterate over one of them, for least amount of iterations which ever is shortest, and use the has() method to see if that character was in the other Set
var counter = 0;
for(letter of inputSet){
if(numberSet.has(letter)){
counter++;
}
}
// on ".check" click...
$(".check").click(function() {
var nmb = new Set( $(".number").text() );
var ltr = new Set( $(".input").val() );
var count = $(".cnt");
var counter = 0;
for(let letter of nmb){
if(ltr.has(letter)){
counter++;
}
}
//No need to continually update text / html as each update wont be
//seen anyway so just set it once outside the loop.
count.text(counter);
$(".res1").html(" numbers in common");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Generated Number: <span class="number">4410</span><br><br>
<input type="text" class="input" placeholder="Try typing 4 to see the issue" maxlength="4">
<input class="check" type="submit" value="CHECK">
<br><br>
<span id="full_res">
<span class="cnt"></span>
<span class="res1"></span>
</span>
You can do something like:
$(".check").click(function() {
var nmb = $(".number").text().trim().split(''); //Get the text and convert to string
var ltr = $(".input").val().trim().split(''); //Get the value and convert to string
var commonLetters = []; //The common letters will be stored on this variable
ltr.forEach(function(v) { //Loop thru the user's input letters
var idx = nmb.indexOf(v); //Find its index
if (idx !== -1) { //Check if found
commonLetters.push(4); //If found, push the letters to commonLetters
nmb[idx] = ''; //Clear the index
}
})
$(".cnt").text(commonLetters.length);
$(".res1").html(" numbers in common");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Generated Number: <span class="number">4410</span><br><br>
<input type="text" class="input" placeholder="Try typing 4 to see the issue" maxlength="4">
<input class="check" type="submit" value="CHECK">
<br><br>
<span id="full_res">
<span class="cnt"></span>
<span class="res1"></span>
</span>
It's not entirely trivial. For example, you can't simply use filter or includes or has tests on their own because once a character is found, you have to remove it from each collection so it doesn't get matched again. I would use reduce and splice the array of characters to remove the found character every time a match is found. (No need for jQuery for this)
document.querySelector('.check').addEventListener('click', () => {
const numChars = [...document.querySelector('.number').textContent];
const inputChars = [...document.querySelector('.input').value];
const matchingCharCount = inputChars.reduce(
({ remainingNumChars = numChars, matchCount = 0 } = {}, inputChar) => {
if (remainingNumChars.includes(inputChar)) {
remainingNumChars.splice(remainingNumChars.indexOf(inputChar), 1);
matchCount++;
}
return { remainingNumChars, matchCount };
}, { remainingNumChars: numChars, matchCount: 0 })
.matchCount;
document.querySelector('.cnt').textContent = matchingCharCount;
document.querySelector('.res1').textContent = " numbers in common"
});
Generated Number: <span class="number">4410</span><br><br>
<input type="text" class="input" maxlength="4">
<input class="check" type="submit" value="CHECK">
<br><br>
<span id="full_res">
<span class="cnt"></span>
<span class="res1"></span>
</span>
I would like to calculate and populate the grand total automatically before submiting the form. The grand total will base on my 5 input fields.
<input type="number" name="inspection_fee">
<input type="number" name="storage_fee">
<input type="number" name="local_fee">
<input type="number" name="cert_fee">
<input type="number" name="others_fee">
<input type="number" name="total_fee">
I know how to do it the php way like it would put variables after I submit it then calculate it totally like this.
<?php
$inspection_fee = $paymentSettings->inspection_fee;
$storage_fee = $paymentSettings->storage_fee;
$cert_fee = $paymentSettings->cert_fee;
$local_fee = $paymentSettings->local_fee;
$others_fee = $paymentSettings->others_fee;
$total_fee = $inspection_fee + $storage_fee + $cert_fee + $local_fee + $others_fee;
?>
But how would I populate the total before submiting it using javascript? Like if I change the inspection fee the total fee will auto adjust depends on the total value.
Looking for help.
Thanks in advance.
Set the total input field to read-only
Create a function to add up all the inputs and set the value in total_fee (good opportunity to use Array.prototype.reduce)
Bind your function to the inputs input event
const inputs = ['inspection_fee', 'storage_fee', 'local_fee', 'cert_fee', 'others_fee']
const total = document.querySelector('input[name="total_fee"]')
const sumTotal = () => {
total.value = inputs.reduce((sum, input) =>
sum += parseInt(document.querySelector(`input[name="${input}"]`).value || 0, 10), 0)
}
inputs.forEach(input => {
document.querySelector(`input[name="${input}"]`).addEventListener('input', sumTotal, false)
})
<input type="number" name="inspection_fee">
<input type="number" name="storage_fee">
<input type="number" name="local_fee">
<input type="number" name="cert_fee">
<input type="number" name="others_fee">
<input type="number" name="total_fee" readonly>
Attach onblur event to all input fields to call a JavaScript function. I have changed the "name" attribute to "id" attribute to be used in the JS function.
<input type="number" id="inspection_fee" onblur="calculateTotalFee();">
<input type="number" id="storage_fee" onblur="calculateTotalFee();">
<input type="number" id="local_fee" onblur="calculateTotalFee();">
<input type="number" id="cert_fee" onblur="calculateTotalFee();">
<input type="number" id="others_fee" onblur="calculateTotalFee();">
<br/>
<input type="number" id="total_fee">
<script type="text/javascript">
function calculateTotalFee(){
var totalFee = 0;
var inspectionFee = document.getElementById("inspection_fee").value.trim() === "" ? 0 :
document.getElementById("inspection_fee").value.trim();
var storageFee = document.getElementById("storage_fee").value.trim() === "" ? 0 :
document.getElementById("storage_fee").value.trim();
var localFee = document.getElementById("local_fee").value.trim() === "" ? 0 :
document.getElementById("local_fee").value.trim();
var certFee = document.getElementById("cert_fee").value.trim() === "" ? 0 :
document.getElementById("cert_fee").value.trim();
var othersFee = document.getElementById("others_fee").value.trim() === "" ? 0 :
document.getElementById("others_fee").value.trim();
totalFee = parseInt(inspectionFee) + parseInt(storageFee) +
parseInt(storageFee) + parseInt(localFee) + parseInt(certFee) + parseInt(othersFee);
document.getElementById("total_fee").value = totalFee;
}
</script>
For my code, I am trying to call 2 parameters into a function. Once you have left the 2nd input box, and multiply the 2 numbers passed through and put it in the third text box. if either of the first 2 input boxes are empty, then color them light red. This is my code so far, what am I missing?
Javascript:
function multiply(one, two) {
if(one==""){
this.style.color='red';
}
if(two==""){
this.style.color='red';
}
else{
txt1=one * two;
return txt1;
}
}
HTML5:
First Value: <input type="text" name="mFirst" />
Second Value: <input type="text" name="mLast" onblur="multiply(mFirst.value, mLast.value)" />
Multiplication of First and Second Value: <input type="text" name="answer">
<input … onblur="multiply.call(this,this.form.elements.mFirst.value,this.form.elements.mLast.value)" >
function multiply(one, two) {
if(one && two){
this.form.elements.answer.value = one * two;
} else {
this.style.color='red';
}
}
Empty strings are non-truthy values, thus one && two will only be true if neither value is an empty string.
Using call allows you to set the value of this used inside the function.
Demo: http://jsfiddle.net/b5Ltt/
You might want to look at the HTML5 <output> element.
You are not passing this to your multiply() function.
If you want to change this.style you can pass this as an argument.
Also, you should change mFirst.value to this.form.elements.mFirst.value and the same for mLast.value
HTML:
First Value: <input type="text" name="mFirst" />
Second Value: <input type="text" name="mLast" onblur="multiply( this , mFirst.value, mLast.value)" />
Multiplication of First and Second Value: <input type="text" name="answer">
JavaScript:
function multiply( _this, one, two) {
var txt1 = 0;
if(one=="" || two==""){
// Should set both colors to red
_this.form.elements.mFirst.style.color = 'red';
_this.form.elements.mLast.style.color= 'red';
}else{
// parse float in the case of a decimal and set de
one = parseFloat(one);
two= parseFloat(two);
txt1 = one * two;
_this.form.elements.answer.value = txt1;
}
}
First Value: <input type="text" name="mFirst" id="mFirst" />
Second Value: <input type="text" name="mLast" id="mLast" onblur="multiply()" />
Multiplication of First and Second Value: <input type="text" name="answer" id="answer" />
function multiply()
{
var num_one = document.getElementById('mFirst').value;
var num_two = document.getElementById('mLast').value;
if(typeof num_one === 'number' && typeof num_two === 'number')
{
document.getElementById('answer').value = (parseInt(num_one) * parseInt(num_two));
}
else
{
document.getElementById('answer').style.color = 'red'; // not recommended method
}
}
Using a similar note, why this doesn't work?
function monetaryfields()
{
if (multiply) { total.value = unitary.value * quantity.value; }
else { unitary.value = total.value / quantity.value; }
}
<form>
<ul>
<li>Quantity: <input type="text" name="quantity" onblur="monetaryfields.call(true)" /></li>
<li>Unitary: <input type="text" name="unitary" onblur="monetaryfields.call(true)" /></li>
<li>Total: <input type="text" name="total" onblur="monetaryfields.call(false)" /></li>
</ul>
</form>