I do not know what I am doing wrong. For some reason I can not add this class to the #total-weight with JS. The CSS is fine because I have hard coded and is working. The sum is working perfect as well.
/********** This is my HTML **************/
<tr id="results">
<td>Grade (%)</td>
<td><input type="text" value="" id="final-grade" name="final-grade"></td>
<td><input type="text" value="100" id="total-weight" name="total-weight"><span><small> remaining (%)</small></span></td>
</tr>
/******** This is my JS ***************/
'use strict';
$(document).on('keyup', '.weight-value', function() {
// the sum of weight (%)
var sumWeight = 0;
var totalWeight = 0;
$('.weight-value').each(function(){
sumWeight += +$(this).val();
});// end of sum of weight (%)
// populate weigth remaining
totalWeight = $('#total-weight').val(100 - sumWeight);
if(totalWeight < 0) {
$('#total-weight').addClass('table-border');
}
});// end document .on keyup
$('#total-weight').val(100 - sumWeight) will set the value of the element and return a jQuery object. So your condition will not work.
Also you might want to use toggleClass(), since you want to remove the class if the value is >=0
'use strict';
$(document).on('keyup', '.weight-value', function () {
// the sum of weight (%)
var sumWeight = 0;
var totalWeight = 0;
$('.weight-value').each(function () {
sumWeight += +$(this).val();
}); // end of sum of weight (%)
// populate weigth remaining
totalWeight = 100 - sumWeight;
$('#total-weight').val(totalWeight);
$('#total-weight').toggleClass('table-border', totalWeight < 0);
}); // end document .on keyup
Demo: Fiddle
Related
I have 4 fields for me to do the calculation, they should add up together and give me the total sum. However, there are some problems with fields when it is empty.
The code and script is below:
<tr id="row">
<td>No. of Dependant(s)</td>
<td><input type="text" id="Dep-main" value="0"></td>
<td><input type="text" id="Dep-joint1" value="0"></td>
<td><input type="text" id="Dep-joint2" value="0"></td>
<td><input type="text" id="Dep-joint3" value="0"></td>
<td><input type="text" id="Total-dep" readonly></td>
</tr>
The script:
<script>
var main = document.getElementById("Dep-main");
var joint1 = document.getElementById("Dep-joint1");
var joint2 = document.getElementById("Dep-joint2");
var joint3 = document.getElementById("Dep-joint3");
var total = document.getElementById("Total-dep");
1
var inputs = Array.prototype.slice.call(document.querySelectorAll("td > input"));
inputs.forEach(function (input) {
input.addEventListener("blur", function () {
// Always supply the second argument to parseInt() (the radix) so you
// dont' get non-base 10 answers.
if (main.value.length === 0) {
total.value = parseFloat(joint1.value) + parseFloat(joint2.value) + parseFloat(joint3.value);
} else if (joint1.value.length === 0) {
total.value = parseFloat(main.value) + parseFloat(joint2.value) + parseFloat(joint3.value);
} else if (joint2.value.length === 0) {
total.value = parseFloat(main.value) + parseFloat(joint1.value) + parseFloat(joint3.value);
} else if (joint3.value.length === 0) {
total.value = parseFloat(main.value) + parseFloat(joint1.value) + parseFloat(joint2.value);
}else{
total.value = parseFloat(main.value) + parseFloat(joint1.value) + parseFloat(joint2.value) + parseFloat(joint3.value);
}
});
});
</script>
However, if there is 2 or more fields are empty, the Total field will appear NaN. Is there any way for me to keep the field as empty and get the total number?
My original idea was flawed in that it would not update the final value if a field was subsequently cleared of a value. Using an object to maintain the values for any element that has received the blur event and then performing a sum calculation of the values seems to work OK.
var total = {};
/* returns numeric value of field or zero if empty etc */
function fieldvalue(id){
var field=document.getElementById( id );
return field.value!='' && field.value.length > 0 && !isNaN( parseFloat( field.value ) ) ? parseFloat( field.value ) : 0;
}
var col=document.querySelectorAll('tr#row > td > input:not([readonly])');
if( col ){
for( var n in col )if( col[ n ].nodeType==1 ){
col[n].addEventListener('blur',function(event){
total[ this.id ]=fieldvalue( this.id );
document.getElementById('Total-dep').value=Object.values(total).reduce(function(a,b){return a+b;});
}.bind( col[n] ),false);
}
}
or, more akin to the original code using Array.prototype.slice
/*
The aim here is to select all input elements that are not marked
as "readonly" as it is these that will be used for the calculations
whilst the "readonly" field is updated programmatically only.
*/
var col=document.querySelectorAll('tr#row > td > input:not([readonly])');
/*
Convert array-like object into a true array in order that we can use
Array.forEach() method which does not work for all browsers when dealing
with HTMLCollections - such as a nodelist
*/
var inputs = Array.prototype.slice.call( col );
inputs.forEach(function(e){
/*
Assign the `onblur` event handler to each of the input elements
- the callback to the event handler will update the `total` object
which is then later processed to calculate the sum of values stored.
*/
e.addEventListener('blur',function(event){
/*
Update the total object with field value
*/
total[ this.id ]=fieldvalue( this.id );
/*
Update the "readonly" field with calculated sum of values
*/
document.getElementById('Total-dep').value=Object.values( total ).reduce(function(a,b){return a+b;});
}.bind( e ),false);
});
Perhaps worth noting is the use of Object.values(obj) - it is not supported by all browsers ( IE, Opera & Safari for instance ) but there are polyfills available here and here
And, I just wrote this - not stringently tested btw
if( typeof( Object.values )!='function' ){
Object.prototype.values=function(obj){
var tmp=[];
var keys=Array.prototype.slice.call( Object.keys( obj ) );
keys.forEach(function( item ){
tmp.push( obj[item] )
});
return tmp;
};
}
i would loop the fields, and if contains something add it.
total.value = 0;
if (main.value.length === 0) {
total.value += parseFloat(main.value);
}
if (join1.value.length === 0) {
total.value += parseFloat(join1.value);
}
if (join2.value.length === 0) {
total.value += parseFloat(join2.value);
}
if (join3.value.length === 0) {
total.value += parseFloat(join3.value);
}
I did not get what you are really after. However, I believe using such checks will lead you to the solution:
var x = $("#someFloatExpectedInput").val();
var y = $("#someIntExpectedInput").val();
if (!isNaN(parseFloat(x))) {
//
}
if (!isNaN(parseInt(y))) {
//
}
You are checking null value in if else statement that why you are getting the error so you need to check separately
Just do like this
var total=0;
if (main.value.length != 0) {
total = total+parseFloat(main.value);
}
if (joint1.value.length != 0) {
total = total+parseFloat(joint1.value);
}
if (joint2.value.length != 0) {
total = total+parseFloat(joint2.value);
}
if (joint3.value.length != 0) {
total = total+parseFloat(joint3.value);
}
total.value = total
It will help you to solve our issue.
I would like to balance two input number fields using jquery based on the max value set for both. for example its like a balance, if one side goes down the other goes up and vice versa. another example if the max value is 20 then if i enter 5 in input field one then 15 would be left in input field two.
Need the help Thanks. Haven't started coding it as yet stuck trying to figure it out.
First you need to attach the input eventhandler on all of the relevant input fields. This event handler will compare the current input value of a input fields to the total/max value variable and find the remainder accordingly. The event handler then finds the other input fields and assigns them with the appropriate remainder values.
Note: This allows you to add as many inputs as you want and it will
balance them all out. Just remember to add the balance class on the
input field.
var total = 20;
$('.balance').on('input', function() {
var value = parseInt(this.value);
if (isNaN(value)) {
this.value = value = 0;
} else if (value > total) {
this.value = value = total;
}/* else if (value < 0) {
this.value = value = 0;
}
* Remove this comment if value shouldn't be negative.
*/
var remainder = total - value;
var otherInputs = $('.balance');
otherInputs.splice($.inArray(this,otherInputs),1);
var remainderDiv = remainder/otherInputs.length;
$.each(otherInputs, function(input) {
otherInputs[input].value = remainderDiv;
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" class="balance">
<input type="number" class="balance">
Update: The two inputs can be less than the max but never higher.
var max = 20;
$('.balance').on('input', function() {
var value = parseInt(this.value);
if (isNaN(value)) {
value = 0;
}
var otherInputs = $('.balance');
var sum = 0;
$.each(otherInputs, function(input) {
sum += parseInt(otherInputs[input].value);
});
if (sum > max)
this.value = max - (sum - value);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="number" class="balance">
<input type="number" class="balance">
here's a fiddle to get you started (and maybe finished):
https://jsfiddle.net/ahmadabdul3/xwyrrw53/1/
html:
<input type='number' id='first' class='balancable'/>
<input type='number' id='second' class='balancable'/>
js:
$(function() {
var max = 20;
var balanceOpposite = {
'first': 'second',
'second': 'first',
}
$('.balancable').on('input', function() {
var id = $(this).attr('id');
var thisVal = $(this).val();
$('#' + balanceOpposite[id]).val(20 - thisVal);
});
});
I have a form, with a table inside.
Each row 4 columns:
Item Name
Item Price (this is set by me, not user)
Quantity (set by user input)
Total (price*qty)
I want it to reflect totals live.
JSFiddle:
http://jsfiddle.net/uyyzkLny/
Code Snippet:
<tr class="txtMult">
<td>Salmon</td>
<td class="val1" type="number">28</td>
<td><input name="Fish1" class="val2" size="2px"/></td>
<td><span class="multTotal">0.00</span></td>
</tr>
--
$(document).ready(function () {
$(".txtMult input").keyup(multInputs);
function multInputs() {
var mult = 0;
// for each row:
$("tr.txtMult").each(function () {
// get the values from this row:
var $val1 = $('.val1', this).val();
var $val2 = $('.val2', this).val();
var $total = ($val1 * 1) * ($val2 * 1)
$('.multTotal',this).text($total);
mult += $total;
});
$("#grandTotal").text(mult);
}
});
Issue:
Keep getting 0. (or NaN). From what I know about Jquery, the issue is that I'm treating val1 as user input instead of hard-coded. How do I fix that? Is that the problem?
TIA
You can't use .val on a td, so you need to get the .text() of the element, and parse it as an integer (optional, but a good idea):
var $val1 = parseInt($('.val1', this).text())
http://jsfiddle.net/uyyzkLny/2/
Here's a fiddle that will give you a start - just a different approach - FIDDLE.
Key points:
uses HTML limiters to keep number to an integer between 0 and 10
'$' is stripped off for the calculation and then put back for the total.
JS
$('input[type=number]').change( function(){
$('.mytable tr td:nth-child(2)').each( function(index, element){
var price = $(this).text().slice(1);
var number = $(this).closest('td').next('td').find('input').val();
var total = (price * number).toFixed(2);
$(this).closest('td').next('td').next('td').text('$' + total );
console.log(price + ' *** ' + number + ' *** ' + total);
});
});
Use
$('.val1', this).text()
instead of
$('.val1', this).val();
Updated fiddle here
I have a table that sum Columns and Rows, and shows the result of the sum.
I have to change the color of each total. If is even, put it "green". If it is odd put it "red"
This is my table:
<table id="sum_table">
<tr>
<td><input value="0" class="sum1" /></td>
<td><input value="0" class="sum2"/></td>
<td><input value="0" class="sum3"/></td>
<td class="total">0</td>
</tr>
<tr>
<td><input value="0" class="sum1"/></td>
<td><input value="0" class="sum2"/></td>
<td><input value="0" class="sum3"/></td>
<td class="total">0</td>
</tr>
<tr>
<td><input value="0" class="sum1"/></td>
<td><input value="0" class="sum2"/></td>
<td><input value="0" class="sum3"/></td>
<td class="total">0</td>
</tr>
<tr class ="totalCol">
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
</table>
<button id="tabla">+</button>
JQuery:
//Sumamos las columnas
$(document).on('keyup change','#sum_table tr:not(.totalCol) input:text',function() {
var $table = $(this).closest('table');
var total = 0;
var thisNumber = $(this).attr('class').match(/(\d+)/)[1];
$table.find('tr:not(.totalCol) .sum'+thisNumber).each(function() {
total += parseInt(this.value);
});
$table.find('.totalCol td:nth-child('+thisNumber+')').html(total);
});
//AƱadimos filas y coumnas cuando se clica al boton "+".
$("#tabla").click(function () {
$("#sum_table tr:last-child").before("<tr>"+$("#sum_table tr:eq(0)").html()+"</tr>");
$("tr:not(:last-child)").each(function () {
var classname = $(this).find("td:last-child").index() + 1;
$(this).find("td:last-child").before('<td><input class="sum' + classname + '" type="text" value="0"></td>');
});
$("#sum_table tr:last-child").append("<td>0</td>");
});
//Creamos la funcion newSum para hacer la suma y mostrarlo en el total.
$(document).on('keyup','input',newSum);
function newSum() {
var sum = 0;
var thisRow = $(this).closest('tr');
var total = 0;
$(thisRow).find("td:not(.total) input").each(function () {
sum += parseInt(this.value);
});
$(thisRow).find(".total").html(sum);
$('.total').each(function () {
total += parseInt($(this).html());
});
}
DEMO JSFIDDLE
Try this, put this code below in newSum() function
if ((this.value % 2 == 0)) {
$(this).css('color', 'green');
} else {
$(this).css('color', 'red');
}
DEMO
I have updated your fiddle please check.
$(document).on('keyup change','#sum_table tr:not(.totalCol) input:text',function() {
var $table = $(this).closest('table');
var total = 0;
var thisNumber = $(this).attr('class').match(/(\d+)/)[1];
$table.find('tr:not(.totalCol) .sum'+thisNumber).each(function() {
total += parseInt(this.value);
});
var total_field = $table.find('.totalCol td:nth-child('+thisNumber+')');
total_field.html(total);
if(total % 2 == true) {
total_field.css("background","red");
}
else {
total_field.css("background","green");
}
});
try this way
JQUERY CODE:
if (total % 2 == 0)
$table.find('.totalCol td:nth-child(' + thisNumber + ')').css('color', 'green'); //set green to even total
else
$table.find('.totalCol td:nth-child(' + thisNumber + ')').css('color', 'red'); //set red to odd total
LIVE DEMO:
http://jsfiddle.net/hdhZZ/7/
Happy Coding :)
Each time one of the inputs is changed, check to see if the total value is an odd or even number...
This is rough, I would toggle a class rather than edit the inline css..
$('td input').on('change', function(){
$('.totalCol td').each(function(){
var $total = parseInt($(this).html());
if ($total !==0 && $total % 2 === 0) {
$(this).css('background-color','green');
}
else {
$(this).css('background-color','#fff');
}
});
});
I realise you've already accepted an answer, but I'd suggest rewriting your approach to the following (though the colouring approach is the same as suggested by the the other answers):
function sumTotals(){
// caching variables:
var table = $('#sum_table'),
inputRows = table.find('tr:not(.totalCol)'),
inputCells = inputRows.find('td:not(.total)');
// iterating over each of the 'td' elements in the '.totalCol' row:
$('.totalCol td').each(function(i,e){
/* i is the index of the current element over which we're iterating
among the collection returned by the selector,
e is the element (the 'this'), which we're not using here.
We're using ':nth-child()' to look at the 'input' elements from
each column, and creating an array of the values using 'map()'
and 'get()': */
var sum = inputRows.find('td:nth-child(' + (i + 1) + ') input').map(function(){
return parseFloat(this.value) || 0;
}).get().reduce(function (prev, curr) {
/* 'reduce()' allows us to perform a calculation (summation) of the
values in the returned array: */
return prev + curr;
});
// setting the text of the current 'td' to the sum,
// using CSS to set the color to either green (even) or red (odd):
$(this).text(sum).css('color', sum % 2 === 0 ? 'green' : 'red');
});
/* iterating over each of the rows with inputs, finding the
last 'td', and updating its text: */
inputRows.find('td:last-child').text(function(){
// caching:
var $this = $(this),
/* getting all the previous 'td' elements, and their 'input'
descendant elements, mapping their values: */
sum = $this.prevAll('td').find('input').map(function(){
return parseFloat(this.value) || 0;
}).get().reduce(function (prev, curr) {
return prev + curr;
});
// setting the color (as above):
$this.css('color', sum % 2 === 0 ? 'green' : 'red');
return sum;
});
}
$('#sum_table').on('keyup change input paste', 'tr:not(.totalCol) input', sumTotals);
JS Fiddle demo.
References:
CSS:
:last-child.
:nth-child().
JavaScript:
Array.prototype.reduce().
parseFloat().
jQuery:
css().
find().
get().
map().
on().
prevAll().
text().
I have a large HTML table that is updated automatically every 24 hours with new data. the 5th column contains multiple numbers in each row separated by a line break, each containing class .remaining-detail. I'm looking to add the numbers from each row, and then find which row contains the largest sum from column 5.
<table>
<tr class="row-3 odd">
<td class="column-1 ">ID</td><br><br><td class="column-2 "> Name<br>
<br><td class="column "> Area<br>
<br>
</td><td class="column-3 ">$5</td><td class="column-4 "> <div class="remaining-detail">$100,000.00</div>
<div class="remaining-detail">$10,000.00</div>
<div class="remaining-detail">$1,000.00</div>
<div class="remaining-detail">$500.00</div>
<div class="remaining-detail">$400.00</div>
<div class="remaining-detail">$100.00</div><br><br>
</td><td class="column-5 "> <div class="remaining-detail">1</div><br>
<div class="remaining-detail">0</div><br>
<div class="remaining-detail">36</div><br>
<div class="remaining-detail">64</div><br>
<div class="remaining-detail">100</div><br>
<div class="remaining-detail">972</div><br>
</td>
</tr></table>
<br>
I am adding these numbers like this:
$(document).ready(function(){
var sum = 0;
$('.row-2 .column-5 .remaining-detail').each(function () {
sum += parseInt($(this).html().replace(',',''));
});
$('#sum2').text(sum);
});
This works for a single instance. How would I go about doing this for .ROW N .column-5 .remaining-detail and then find the row with the largest sum?
Here is a fiddle with what I have right now: http://jsfiddle.net/3LHb8/
You can do that with two nested .each() loops. Here's an example:
$(document).ready(function(){
var sums = [];
$('tbody tr').each(function() {
var rowSum = 0;
$(this).find('.remaining-detail').each(function () {
rowSum += parseInt($(this).html().replace(',',''));
});
sums.push(rowSum);
});
$('#sum2').text("Biggest sum is in row " + (1 + sums.indexOf(Math.max.apply(Math, sums))));
});
Here's the jsFiddle. I'm storing the sums of each row and then printing the row with the highest sum, but you can do whatever variation you need. Hope it helps.
Hoefully this is what you are looking for
$(document).ready(function(){
var maxsum = 0;
$(".column-5").each(function(){
alert('inside');
var coloumnSum = 0;
$(this).find(".remaining-detail").each(function(){
coloumnSum = coloumnSum + parseInt($(this).html(), 10);
});
if(maxsum < coloumnSum){
maxsum = coloumnSum;
}
});
alert(maxsum);
});
It's hard to tell with no html... Can you share at least 2 rows of your html table and we can help.
oh well, you can try something like this:
var sum = 0;
var sum2 = 0;
var trIndex = 0;
$('.row-2 .column-5').each(function () {
sum = 0;
$(this').find('.remaining-detail').each(function () {
sum += parseInt($(this).html().replace(',',''));
});
if (sum > sum2)
{
sum2 = sum;
trIndex = $(this).parents('tr').index();
}
});
}
alert('row='+trIndex+' sum='+sum2);
$('tr').eq(trIndex-1).css('background-color','#ff0000');
EDIT
Thanks for sharing some html, let us know if the example code we provide works for you :)