How to sum up all dynamic inputs in js - javascript

How can I get all the sum of these inputs? Sometime they have a value from the database, sometimes no value and needs to be inputted. I'm using jquery for this.
Please see the code below:
$(document).ready(function(){
$('input[name=grade\\[\\]]').on('focus, keyup', function(){
var points = $('input[name=grade\\[\\]]');
var totals = points.get()
.map(function(sel){
return parseFloat(sel.value, 10);
})
.reduce(getSum, 0);
if(points.length == 1){
$('input[name=total]').val($(this).val());
} else if(points.length > 1 && totals < 100){
$('input[name=total]').val(totals);
}
});
function getSum(total, value){
return total + parseFloat(value, 10);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<input type="text" name="grade[]" ><br><br>
<input type="text" name="grade[]" ><br><br>
<input type="text" name="grade[]" ><br><br>
<input type="text" name="grade[]" ><br><br>
<input type="text" name="grade[]" ><br><br><br>
Total<br>
<input type="text" name="total" readonly>
</form>

The problem is that parseFloat() returns NaN when the value can't be parsed as a number, and the result of adding up a list that includes some NaN values will be NaN. Which means your if/else that decides whether to display the total won't display it because NaN < 100 is false.
Given that your inputs are empty to start with those items are parsed as NaN.
The simplest fix is to change this line in your .map() function:
return parseFloat(sel.value, 10);
to be:
return parseFloat(sel.value) || 0;
...where the || operator will return the left-hand operand if it is a truthy value, i.e., a number, not NaN or 0, and otherwise return the right-hand operand 0. That is, blank or otherwise non-numeric values will be treated as if they were 0.
You don't need to call parseFloat() again in your getSum() function, because by then you already have numbers.
(Note also that parseFloat() doesn't take a second argument, you've mixed that up with parseInt().)
$(document).ready(function() {
$('input[name=grade\\[\\]]').on('focus, keyup', function() {
var points = $('input[name=grade\\[\\]]');
var totals = points.get()
.map(function(sel) {
return parseFloat(sel.value) || 0; // <-- this is the line that changed
})
.reduce(getSum, 0);
if (points.length == 1) {
$('input[name=total]').val($(this).val());
} else if (points.length > 1 && totals < 100) {
$('input[name=total]').val(totals);
}
});
function getSum(total, value) {
return total + value; // <-- no need for parseFloat() here
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<input type="text" name="grade[]">
<input type="text" name="grade[]">
<input type="text" name="grade[]">
<input type="text" name="grade[]">
<input type="text" name="grade[]"><br><br><br> Total
<br>
<input type="text" name="total" readonly>
</form>
(I've removed most of the <br> elements just to avoid having to scroll down to see the total for demo purposes.)

Related

How can I pattern match ID only making sure the variable number matches without having to hardcode all of the possibilities?

I've recently become familiar with Jquery selectors....and they work great. Starts with...ends with....
The problem I have currently is that all of my variable names essentially start with similar patterns and end with similar patterns. This ID is generated from somewhere else so I'm hoping I can do something to use it effectively.
The pattern ID format essentially looks like...
"#id_newbudgetlineitem_set-0-line_item_october"
"#id_newbudgetlineitem_set-0-line_item_november"
"#id_newbudgetlineitem_set-0-line_item_december"
I want to essentially matching on the set-* but only if it's identical to the other ids in my array. Is this even possible without having to hard code anywhere from set-0 to set-1000? Unfortunately the class for each one is the same as is the name situation. Is there someway to say if the set numbers all match in a given array then add them up? I can't use starts with or ends with in this case...and don't want to hardcode 1000 possibilities. Thanks in advance for any ideas or thoughts.
I am trying to do something like.....
function update_total()
{
var total = 0;
$('.budget').each(function(index, element) {
"#id_newbudgetlineitem_set-0-line_item_october" +
"#id_newbudgetlineitem_set-0-line_item_november" +
"#id_newbudgetlineitem_set-0-line_item_december"
var val = parseFloat($(element).val());
if( !isNaN( val )){
total += val;
}
});
$("#id_total").val(total);
}
Here's a working solution........
function update_total_total_total()
{
var ret = +$("input[name$='set-0-line_item_january']").val() + +$("input[name$='set-0-line_item_february']").val() + +$("input[name$='set-0-line_item_march']").val() + +$("input[name$='set-0-line_item_april']").val() + +$("input[name$='set-0-line_item_may']").val() + +$("input[name$='set-0-line_item_june']").val() + +$("input[name$='set-0-line_item_july']").val() + +$("input[name$='set-0-line_item_august']").val() + +$("input[name$='set-0-line_item_september']").val() + +$("input[name$='set-0-line_item_october']").val() + +$("input[name$='set-0-line_item_november']").val() + +$("input[name$='set-0-line_item_december']").val();
$("input[name$='set-0-line_item_total']").val(ret);
}
But I could have up to 1000 different set values. Is there some other way to do this without having to hard code this 999 more times?
This is a lot closer....but total still says 0. It's updating all of the totals to 0...so that's progress but not getting the actual totals. Forward progress thanks to Swati.
function update_total_total_total() {
//get length of input line_total for each sets..
for (var i = 0; i < $("[name$=line_item_total]").length; i++) {
var total = 0;
//get all inputs but not line_item _total
$(`input[name*=id_newbudgetlineitem_set-${i}-line_item]:not([name$=line_item_total]):not([name$=line_item_cost_center]):not([name$=line_item_description])`).each(function(index, element) {
var val = parseFloat($(element).val());
if( !isNaN( val )){
total += val;
}
})
$(`input[id$=set-${i}-line_item_total]`).val(total); //set value..of input
}
}
You can get length of total input whose name ends with line_item_total so this value will be counter for for-loop.
Then , inside for loop you can use $(`input[name*=id_newbudgetlineitem_set-${i}-line_item]:not([name$=line_item_total])`) this will fetch values from all inputs expect the line_total_item then add value on each iteration .
Lastly , use $(`input[name$=set-${i}-line_item_total]`).val(total); to set total inside line_total_item textbox.
Demo Code :
function update_total_total_total() {
//get length of input line_total for each sets..
for (var i = 0; i < $("[name$=line_item_total]").length; i++) {
var total = 0;
//get all inputs but not line_item _total
$(`input[name*=id_newbudgetlineitem_set-${i}-line_item]:not([name$=line_item_total]):not([name$=line_item_cost_center]):not([name$=line_item_description])`).each(function(i, element) {
var val = parseFloat($(element).val());
if (!isNaN(val)) {
total += val;
}
})
$(`input[name$=set-${i}-line_item_total]`).val(total); //set value..of input
}
}
update_total_total_total()
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
SET 0 :
<input type="text" name="id_newbudgetlineitem_set-0-line_item_october" value="5">
<input type="text" name="id_newbudgetlineitem_set-0-line_item_november" value="51">
<input type="text" name="id_newbudgetlineitem_set-0-line_item_december" value="15">
<br/> Total :
<input type="text" name="id_newbudgetlineitem_set-0-line_item_total" value="" placeholder="total">
<input type="text" name="id_newbudgetlineitem_set-0-line_item_cost_center">
<input type="text" name="id_newbudgetlineitem_set-0-line_item_description">
</div>
<br/>
<div>
SET 1
<input type="text" name="id_newbudgetlineitem_set-1-line_item_october" value="5">
<input type="text" name="id_newbudgetlineitem_set-1-line_item_december" value="534">
<br/> Total :
<input type="text" name="id_newbudgetlineitem_set-1-line_item_total" value="" placeholder="total">
<input type="text" name="id_newbudgetlineitem_set-1-line_item_cost_center">
<input type="text" name="id_newbudgetlineitem_set-1-line_item_description">
</div>
<br/>
<div>
SET 2
<input type="text" name="id_newbudgetlineitem_set-2-line_item_december" value="4">
<input type="text" name="id_newbudgetlineitem_set-2-line_item_oct" value="5">
<br/> Total :
<input type="text" name="id_newbudgetlineitem_set-2-line_item_total" value="" placeholder="total">
<input type="text" name="id_newbudgetlineitem_set-2-line_item_cost_center">
<input type="text" name="id_newbudgetlineitem_set-2-line_item_description">
</div>
This was the final working code. As Swati suggested it was an incorrect name reference.
function update_total_total_total() {
for (var i = 0; i < $("[name$=line_item_total]").length; i++) {
var total = 0;
$(`input[name*=newbudgetlineitem_set-${i}-line_item]:not([name$=line_item_total]):not([name$=line_item_cost_center]):not([name$=line_item_description])`).each(function(i, element) {
var val = parseFloat($(element).val());
if( !isNaN( val )){
total += val;
}
})
$(`input[name$=set-${i}-line_item_total]`).val(total);
}
}

Limit input to show only thousans in HTML or JS

I have an input filed where the user can enter some numbers. I want to limit the user to enter only thousands.
.
on the image, the user can enter other numbers even if the step is 1000.
onblur is executed when you lose the focus, so try this :
function autoThousand(){
var input = document.getElementById('thousand');
if (input.value%1000 !== 0 ){
input.value-=input.value%1000;
}
}
<input type="number" id="thousand" onblur="autoThousand();" step="1000">
This will round all number inputs to multiples of their step value, when they lose focus. It uses traditional rounding, where it rounds 1499 down to 1000 and 1500 up to 2000. (You can remove the commented line of code to always round down.)
This is one of those "add it and forget it" bits of code, where you just need to add inputs of type number, with a limit, and it will automatically round them all for you.
document.querySelectorAll("input[type=number][limit]").forEach(function(input) {
input.addEventListener("change", function() {
var value = parseInt(this.value, 10);
var limit = parseInt(this.getAttribute("limit"), 10);
value = value + (limit / 2); // remove this to always round down
this.value = value - (value % limit);
});
});
<input type="number" limit="1000" />(multiples of 1000)<br />
<input type="number" limit="100" />(multiples of 100)<br />
<input type="number" limit="500" />(multiples of 500)<br />
use this,
if you still want to make the field number field set the type="number" , step="1000", min="1000" max="any value of your choice"
<input type="text" name="quantity" id="num" onchange="checkInput()">
<script>
function checkInput(){
get_num = new Number(document.getElementById('num').value)
if(get_num < 1000){
document.getElementById('num').value = ""
alert("You must enter number in thousands")
}
}
</script>
Set 'max', 'min' and 'step' value.
<input type="number" name="points" step="1000" max="100000" min="1000">

Trouble getting count of negative number

I have several inputs in the same class and a function that returns false if any of these inputs are empty. What I am trying to do is return false if any of the inputs are negative numbers. I think there might be a way to do this using a regex but am unsure how to go about it.
This is what I have so far.
var $nonneg = $('.quantity').filter(function(){
return this.value < 0;
});
if ($nonneg.length != 0) {
return false;
}
Probably it should be return this.value =='';
The idea is to check if the value for 3 conditions:
equal === to empty string ""
If coercing the value to a Number results in NaN
If the number (when coerced) is less than zero.
You can use Array.prototype.some() to check your conditions and return the value. Here's an example of how it can work:
$(".check-inputs").on("click", function () {
console.log(anyInvalid());
});
function anyInvalid () {
return Array.prototype.some.bind($(".quantity"))(function (elem) {
return elem.value === "" || isNaN(Number(elem.value)) || Number(elem.value) < 0;
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" class="quantity" value="1"/><br/>
<input type="text" class="quantity" value="2"/><br/>
<input type="text" class="quantity" value="3"/><br/>
<input type="text" class="quantity" value="-4"/><br/>
<input type="text" class="quantity" value=""/><br/>
<button class="check-inputs">Check Inputs</button>
I found a solution that works for me, it returns false if it finds a number less than zero. I was making it out to be more complex than it should have been.
var $nonneg = $('.quantity').filter(function(){
return this.value < 0;
});
if ($nonneg.length != 0) {
return false;
}
Use the Array.prototype.every() function to check that every input in the array passes a given test. First, get the inputs as an array using jQuery's .get(). Then run the elements through Array.prototype.every and it will return false if any elements fail the given test.
function arePositiveOrZero(selector){
return $(selector)
.get() // Convert to array
.every( node => parseInt(node.value) >= 0 ) // Check all elements are >= 0
}
// Tests that log to the console
console.log({hasNeg: arePositiveOrZero('.hasNeg')}) // false
console.log({hasBlank: arePositiveOrZero('.hasBlank')}) // false
console.log({hasZero: arePositiveOrZero('.hasZero')}) // true
console.log({allPos: arePositiveOrZero('.allPos')}) // true
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input class="hasNeg" type="text" value="1">
<input class="hasNeg" type="text" value="-1">
<input class="hasZero" type="text" value="0">
<input class="hasZero" type="text" value="1">
<input class="hasBlank" type="text" value="1">
<input class="hasBlank" type="text" value="">
<input class="allPos" type="text" value="2">
<input class="allPos" type="text" value="3">
If you don't want to include zero, just change the test function to node => node.value > 0

JavaScript Set Default Value on Function Not Working?

Function in JS
function punch(){
var a,b,result;
a=document.getElementById('n1').value;
b=document.getElementById('n2').value;
var x=parseInt(a);
var y=parseInt(b);
result=x+y;
if (result===NaN)
result =0;
I know this condtition is false and it gives output of x+y. On empty fields it always return NaN value
when change it to
if (result!==NaN)
result=0;
Now it becomes true but it gives x+y also 0.
document.getElementById('n3').value=result;
}
HTML Code
<input type="text" id="n1" placeholder="Value 1"/>
<input type="text" id="n2" placeholder="Value 2"/>
<button type="button" onClick="punch()">Click For Answer</button>
<input type="text" id="n3" placeholder="Answer"/>
Nothing, including NaN, is ever === to NaN. In fact one way to test for NaN is to exploit that!
if (result !== result)
result = 0; // must have been NaN!
You can also use isNaN():
if (isNaN(result))
result = 0;

Calculate sum and multiply its value

I'm calculating the sum of a and b and putting it in text box named sum.
After I enter a number in number text box, it should calculate the final = sum * number.
<input type="text" class="txt_1_0" name="a" />
<input type="text" class="txt_1_0" name="b" />
<input type="text" id="sum" name="sum" />
<input type="text" class="number" name="number" />
<input type="text" class="final" name="final" />
I tried the following:
$(document).ready(function() {
$(".txt_1_0").change(function() {
var total = 0.00;
var textbox3 = 0.00; // this gonna be your third textbox
$(".txt_1_0").each(function() {
total += parseFloat(this.value) / 5;
});
textbox3 = $("#sum").val((total).toFixed(2));
});
});
How do I get the number value and calculate final?
You haven't actually added any function that would do the final calculation. So to multiply the sum (subtotal) with number, do the following:
$(".number").change(function () {
var final = $("#sum").val() * $(this).val();
$('.final').val(final);
});
Here is a demo - note that I have removed the division by 5 from your previous function as it didn't make sense from the the way your question was asked.
Or you can use keyup event with this jQuery code Fiddle
<script type="text/javascript">
$(document).ready(function(){
$('input[type="text"]').on('keyup',function(){
var a=parseFloat($('.txt_1_0:first').val())
var b=parseFloat($('.txt_1_0:last').val())
if(a && b){$('#sum').val(a+b)}
var number=$('.number').val()
if(number){
$('.final').val($('#sum').val()*number)
}
})
})
</script>

Categories

Resources