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().
Related
I do not understand javascript at all, I study as needed and I need help
I need to sum up the values of certain columns of a table, the rows of which are marked with a checkbox
For example: I mark the checkbox in two rows of the table and the sum of 3,4 and 5 columns is summed up and displayed somewhere on the page
Now I managed to find a piece of code that summarizes the value of the checked checkboxes in the form, and displays it on the page
I need help in replacing the part that receives the "value" of the input, with the one that gets the values of the cells in the stob = head of the table and sums them
Here is this code
var
$form = $("#out_form"),
$allCheckboxes = $("input:checkbox", $form),
$sumOut = $("#checked-sum"),
$countOut = $("#checked-count");
$allCheckboxes.change(function() {
var
sum = 0,
count = 0;
$allCheckboxes.each(function(index, el) {
var
$el = $(el),
val;
if ($el.is(":checked")) {
count++;
val = parseFloat($el.val());
if (!isNaN(val)) {
sum += val;
}
}
});
$sumOut.text(sum);
$countOut.text(count);
});
HTML
<form action="" method="post" id="out_form">
<input type="hidden" name="next" value="{{next}}"/>
<button type="submit">Check</button>
<span id="checked-sum">0</span>
<span id="checked-count">0</span>
{%csrf_token%}
<div class="table-view__container">
<table class="table-view__table">
<tbody class="table-view__body">
{% for out in filter.qs %}
<tr>
<td>
<label class="custom_Label">
<input type="checkbox" name="checked" value="{{ out.id }}">
<span class="checkmark"></span>
</label>
</td>
<td>{{out.date|date:"d(D).m.Y"}}</td>
<td>{{out.ts}}</td>
<td>{{out.pl}}</td>
<td>{{out.rem}}</td>
<td>{{out.comment}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</form>
It is necessary to sum these 3 columns:
...
<td>{{out.ts}}</td>
<td>{{out.pl}}</td>
<td>{{out.rem}}</td>
...
UPD:
I managed to display the amount with the checkbox active, but only the first line:
var
$form = $("#out_form"),
$table = $(".table-view"),
$allCheckboxes = $("input:checkbox", $form),
$sumOut = $("#checked-sum"),
$countOut = $("#checked-count");
$allCheckboxes.change(function() {
var
sum = 0,
count = 0;
$allCheckboxes.each(function(index, el) {
var
$el = $(el),
val;
if ($el.is(":checked")) {
count++;
$form.each(function () {
var val1 = parseInt(document.querySelector(".ts", this).innerHTML,10);
var val2 = parseInt(document.querySelector(".pl", this).innerHTML,10);
var val3 = parseInt(document.querySelector(".rem", this).innerHTML,10);
var total = (val1 * 1) + (val2 * 1) + (val3 * 1);
sum += total;
});
if (!isNaN(val)) {
sum += total;
}
}
});
$sumOut.text(sum);
$countOut.text(count);
});
JavaScript can be confusing, its definitely not an easy programming language. Sorry for not using your code, but I think its overcomplicating things.
So mainly what this code does is to trigger a function using event handlers on all checkboxes, that sums or substracts from the result variable depending if they are checked or unchecked and then show the result in a <span> tag.
Some key points
I used document.querySelectorAll('input[type=checkbox]') to get all the checkbox elements.
The following code is to create one event handler for each checkbox element:
boxes.forEach((box) => {
box.addEventListener("change", function() {
The input checkbox element lives inside a <td></td>, so this.closest('td').nextElementSibling is necessary to get the parent tag and then with the help of nextElementSibling we can get the next <td> element of the table which has the value we need to sum or substract.
Snippet
var boxes = document.querySelectorAll('input[type=checkbox]'),
show = document.getElementById('showResult'), result = 0;
boxes.forEach((box) => {
box.addEventListener("change", function() {
var firstElement = this.closest('td').nextElementSibling,
secondElement = firstElement.nextElementSibling,
firstValue = parseInt(firstElement.innerHTML),
secondValue = parseInt(secondElement.innerHTML);
var sum = firstValue + secondValue;
this.checked ? result += sum : result -= sum;
show.innerHTML = result;
});
});
td {
border: 1px solid #dddddd;
text-align: left;
width:50px;
text-align:center;
}
span{
font-size:20px;
}
<table id="table">
<tr>
<td><input type="checkbox" id="box1" /></td>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td><input type="checkbox" id="box2" /></td>
<td>3</td>
<td>4</td>
</tr>
</table>
<br>
<br>
<span>Result: </span><span id="showResult">0</span>
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 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
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 some problem with dynamic select data from html table.
I give example of table and input, but in fact the table consists of hundreds rows.
<select name="options">
<option value="equal">=</option>
<option value="notequal">!=</option>
<option value="more">></option>
<option value="less"><</option>
</select>
<input type="input" value="input numbers" id="filter">
<table border="1">
<tr>
<td width="150">NAME</td>
<td class="wys">Value</td>
<td>Value2</td>
<td>Value3</td>
</tr>
<tr>
<td width="150">Name1</td>
<td class="wys">65</td>
<td>87</td>
<td>988</td>
</tr>...
So, question is how to hide/show row depending on input data and selected option, assuming that input data refer to column Value
My first solution was:
$("#filter").keyup(function() {
var filter = $("#filter").val();
var options = $("#options").val();
if(options == 'equal'){
$("table td.wys:contains('" + $(this).val() + "')").parent().show();
$("table td.wys:not(:contains('" + $(this).val() + "'))").parent().hide();
}
else if(options == 'notequal'){
$("table td.wys:contains('" + $(this).val() + "')").parent().hide();
$("table td.wys:not(:contains('" + $(this).val() + "'))").parent().show();
}
else if(options == 'more'){
//HOW TO SHOW/HIDE ROW GREATER THAN eg. 100
}
else {
//HOW TO SHOW/HIDE ROW SMALLER THAN eg. 100
}
});
So I found second solution...
var wys = $("table td.wys");
wys.each(function() {
$(this).attr('data-wys', parseInt($(this).text()));
});
I set attributes and parse to int all values from column VALUE
Someone could tell me how to SHOW/HIDE row from table if I select equal, not equal, more or less and press my numer...?
You can use the .filter() method:
// A helper object for doing some math
var operators = {
'equal': function(a, b) { return a == b },
'notequal': function(a, b) { return a != b },
'more': function(a, b) { return a > b },
'less': function(a, b) { return a < b }
};
var $tr = $('tr').not(':first'),
$sel = $("select[name='options']").on('change', function() {
// Trigger the keyup on the select's change event
$("#filter").keyup();
});
$("#filter").keyup(function () {
var v = $.trim(this.value),
o = $sel.val();
// Show all the TRs when the value's length is 0
if (!v.length) return $tr.show();
$tr.hide().filter(function () {
var t = $('.wys', this).text();
return operators[o](t, v);
}).show();
});
http://jsfiddle.net/q2PVm/1/