sum of column using jquery [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I need to sum of column With OnKeyup or OnChange
Here's my code:
$(document).ready(function() {
$(".expenses").on('keyup change', calculateSum);
});
function calculateSum() {
var $input = $(this);
var $row = $input.closest('tr');
var sum = 0;
$row.find(".expenses").each(function() {
sum += parseFloat(this.value) || 0;
});
$row.find(".expenses_sum").val(sum.toFixed(2));
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="1">
<tr>
<th>sl</th>
<th>TA</th>
<th>DA</th>
</tr>
<tr>
<td>1</td>
<td><input class="expenses"></td>
<td><input class="expenses"></td>
</tr>
<tr>
<td>2</td>
<td><input class="expenses"></td>
<td><input class="expenses"></td>
</tr>
<tr>
<td>Total</td>
<td><input class="expenses_sum"></td>
<td><input class="expenses_sum"></td>
</tr>
</table>

This is when the "context" of the input that matters: you want to update the sum that is in the same column where the input element was updated.
What you can do is:
Get the index of the <td> element the input belongs to
Calculate the sum of all expenses belonging to the same column. This is done by filtering (using .filter()) all .expenses elements to ensure that their parent's <td> index matches that you've determined in step 2
Set the sum on the corresponding .expenses_sum element in the same column. This is again, done by filtering all .expenses_sum elements and only getting the one whose parent <td> index matches
Some additional pro-tips:
Listen to the onInput event. For input elements, that covers onKeyUp and onChange events, for convenience.
Use <input type="number" /> to prevent users from erroneously entering non-numerical characters
Use <input readonly /> on the .expenses_sum element, so that users don't fiddle with that sum by their own
Remember to cast the value of the input elements to a number. This can be done by using the + operator, i.e. +this.value. Remember that as per spec, all input elements, regardless their type, always has their value in type of string
Chain .each(calculateSum) to your original selection, so that you also compute the sum when the page is first loaded, i.e. $(".expenses").on('input', calculateSum).each(calculateSum);. This is very helpful when the .expenses elements might be pre-populated with values from the server-side (or if you have manually defined value="..."), for example.
See proof-of-concept below:
$(document).ready(function() {
$(".expenses").on('input', calculateSum).each(calculateSum);
});
function calculateSum() {
// Get the index of the parent `<td>` element
var cellIndex = $(this).closest('td').index();
// Get the values of expenses in the same column as the `<td>` element
var allExpensesInSameColumn = $('.expenses').map(function() {
if ($(this).closest('td').index() !== cellIndex)
return;
return +this.value;
}).get();
// Calculate the sum from returned array of values
var sumOfExpensesInSameColumn = allExpensesInSameColumn.reduce(function(acc, curVal) {
return acc + curVal;
});
// Set the sum on the `.expenses_sum` element in the corresponding column
$('.expenses_sum').each(function() {
if ($(this).closest('td').index() !== cellIndex)
return;
this.value = sumOfExpensesInSameColumn;
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="1">
<tr>
<th>sl</th>
<th>TA</th>
<th>DA</th>
</tr>
<tr>
<td>1</td>
<td><input class="expenses" type="number" /></td>
<td><input class="expenses" type="number" /></td>
</tr>
<tr>
<td>2</td>
<td><input class="expenses" type="number" /></td>
<td><input class="expenses" type="number" /></td>
</tr>
<tr>
<td>Total</td>
<td><input class="expenses_sum" readonly></td>
<td><input class="expenses_sum" readonly></td>
</tr>
</table>

Related

Sort checkbox(checked and unchecked) in table

I want to sort my checkbox when i click on the X:
JS to sort my checkbox(checked and unchecked)?
I got no idea how to write it. please help.
The following code is borrowed.
The Price and stock value will be pass from other JS file using router.
But for now I make it simple because I want to know how to sort the checkbox.
var sortedPrice = false;
function sortPrice() {
$('#myTable').append(
$('#myTable').find('tr.item').sort(function (a, b) {
var td_a = $($(a).find('td.sortPrice')[0]);
var td_b = $($(b).find('td.sortPrice')[0]);
if(sortedPrice){
if(td_a.html() == 'Free') return -1;
return td_b.html().replace(/\D/g, '') - td_a.html().replace(/\D/g, '');
}else{
if(td_a.html() == 'Free') return 1;
return td_a.html().replace(/\D/g, '') - td_b.html().replace(/\D/g, '');
}
})
);
if(sortedPrice) sortedPrice = false;
else sortedPrice = true;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="table" id="myTable">
<tr>
<th onclick="sortPrice()">Price</th>
<th>Stock</th>
<th>%</th>
<th>X</th>
</tr>
<tr class="item">
<td class="sortPrice">1</td>
<td>1</td>
<td>2</td>
<td><input type="checkbox" value="1"></td>
</tr>
<tr class="item">
<td class="sortPrice">4</td>
<td>3</td>
<td>1</td>
<td><input type="checkbox" value="2"></td>
</tr>
<tr class="item">
<td class="sortPrice">7</td>
<td>4</td>
<td>6</td>
<td><input type="checkbox" value="3"></td>
</tr>
<tr class="item">
<td class="sortPrice">2</td>
<td>7</td>
<td>8</td>
<td><input type="checkbox" value="4"></td>
</tr>
<tr class="item">
<td class="sortPrice">3</td>
<td>4</td>
<td>2</td>
<td><input type="checkbox" value="5"></td>
</tr>
</table>
I would try to make the click handler generic by taking the following steps:
Create a function that takes an array of pairs, and sorts that array by the first value in every pair, and returns the sorted array with just the second value from each pair in sorted order. This generic function can be used to pass pairs of cell-content and corresponding row element. This function could also take care of reversing the order when the input pairs were already sorted.
Create a single click handler for the td elements (the column headers). Let it collect the cells in the corresponding column, and for each cell determine whether the checkbox state should be taken as value, or the text content of that cell.
After sorting the values in the column with the first function, the rows can be fed into the table again.
Use the compare function from Intl.Collator so to have numeric sort when appropriate.
This way you can do away with some of the HTML (onclick, sortPrice, item, ...)
const {compare} = new Intl.Collator(undefined, {numeric: true});
function sortSecondByFirst(pairs) {
const sorted = [...pairs].sort(([a], [b]) => compare(a, b))
.map(([,a]) => a);
if (pairs.every(([,a], i) => a === sorted[i])) {
sorted.reverse(); // Was already sorted
}
return sorted;
}
$("th", "#myTable").click(function () {
sortColumn($(this).index());
});
function sortColumn(colIdx) {
const $cells = $(`tr > td:nth-child(${colIdx+1})`, "#myTable");
$("#myTable").append(
sortSecondByFirst($cells.get().map((cell) => {
const $input = $('input[type=checkbox]', cell);
const value = $input.length ? $input.prop("checked") : $(cell).text();
return [
value,
$(cell).parent()
];
}))
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="myTable">
<tr>
<th>Price</th><th>Stock</th><th>%</th><th>X</th>
</tr>
<tr>
<td>1</td><td>1</td><td>2</td>
<td><input type="checkbox" value="1"></td>
</tr>
<tr>
<td>4</td><td>3</td><td>1</td>
<td><input type="checkbox" value="2"></td>
</tr>
<tr>
<td>7</td><td>4</td><td>6</td>
<td><input type="checkbox" value="3"></td>
</tr>
<tr>
<td>20</td><td>7</td><td>8</td>
<td><input type="checkbox" value="4"></td>
</tr>
<tr>
<td>3</td><td>4</td><td>2</td>
<td><input type="checkbox" value="5"></td>
</tr>
</table>
Quite honestly if u have a choice I'd always go use Vue, react or the like as a ui framework. There this is simpler and u have a better -in my eyes - split of html template and data. Vue is quite easy to learn from my experience too.(great tutorials eg on YouTube)
That said in jQuery I guess I would write a sort function like the one u got there that via onclick event it triggered when X is clicked on and for the sorting write a similar compare function as above. Eg
(a,b) => a.checked - b.checked;
Hope this makes sense to you or where precisely do u struggle?

Check boxes values returned and added to string

I am trying to take a row of checkboxes in a table and for each TD in the table it needs to check if the checkbox is ticked, is so it is a 1 and else its 0.
I need a for loop where I will be able to loop over each td, determin if it is checked and if so add a 1 to a binary string or else add a 0 to the binary string.
This should end with each tr having its own unique binary string from the checkboxes that have or have not been ticked. I will also want to set up each tr with its own unique ID.
The below code is what I have so far but am presumming I am going in the wrong direction.
Any help appreciated. Thanks
[ { ID: 000, binary: 0101010101 } ]
function generate(){
$("#actionTable>tbody").children("tr").each(function(i, rowitem){
$(rowitem).children("td").each(function(index, item){
if (index == 0){
var amid = $(item).data("amid");
}
else {
//Handle checkbox
var checked = $(item.firstChild).prop('checked')
}
});
});
}
You can use a nested map() for this. The outer map iterates rows
The inner map iterates each input's checked property converted to number and then to string and then joins the array for final string.
I don't know what the html looks like so have just used the row index of each row for now
const res = $('tr').map((i, el) => {
const binary = $(el).find(':checkbox').map((_, inp) => {
return `${+inp.checked}`;
}).get().join('');
return { index: i, binary};
}).get()
console.log(res)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td><input type="checkbox"></td>
<td><input type="checkbox" checked></td>
<td><input type="checkbox"></td>
<td><input type="checkbox"></td>
</tr>
<tr>
<td><input type="checkbox" checked></td>
<td><input type="checkbox"></td>
<td><input type="checkbox" checked></td>
<td><input type="checkbox"></td>
</tr>
</table>

How to retrieve references from group Checkbox name arrays using JS or jQuery

I have a hard JS/jQuery riddle ! Hard because I couldn't find it on Google nor here, neither now, nor months ago when I was looking for it previously.
A large framework is using checkboxes in a table:
<table class="ListTable">
<tr>
<td><input name="blnChecked[70_20]" type="checkbox" value="1" id="some_unusable_gobbledy_gook" /></td>
<td></td>...
</tr>
<tr>
<td><input name="blnChecked[71_20]" type="checkbox" value="1" id="some_more_unusable_gobbledy_gook" /></td>
<td></td>...
</tr>
<tr>
<td><input name="blnChecked[70_25]" type="checkbox" value="1" id="some_further_unusable_gobbledy_gook" /></td>
<td></td>...
</tr>
</table>
I now need to collect all checkbox name references into an array: 70_20, 71_20 and 70_25 in the above example. Then join them up, and submit them as a URL parameter to a different page (although this joining is not essential to my question).
Question: Using JS/jQuery on the same page, how do I get these references from the name strings in these (checked) checkboxes in an array ?
I prefer not to use regexes (a bit messy, or 'overkill' for such a seeming trivial matter imho), although such a solution is not off my table.
(If someone asks why the table is structured as such: This is not my doing. But I can see that when such a form, in which this table is submitted to a PHP page, the PHP stores all such checkboxes into a single array, which is very nice, and I wanted to achieve a similar effect with JS/jQuery.)
A way to create on client side the array is based on using:
.map()
string .replace()
$('#btn').on('click', function(e) {
var retVal = $('table.ListTable :checkbox[name^="blnChecked["]:checked').map(function(idx, ele) {
//
// if the name value has always the same format...
//
return ele.name.replace('blnChecked[', '').replace(']', '');
//
// or....
//
// return ele.name.split('[').pop().replace(']', '');
// return ele.name.substr(11, 5);
//return ele.name.replace(/blnChecked\[(.*?)\]/g, '$1')
}).get();
var param = $.param({'param': retVal.join(',')});
console.log('Array: ' + retVal);
console.log('URL param: ' + param);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="ListTable">
<tr>
<td><input name="blnChecked[7125_2355]" type="checkbox" value="1" id="some_unusable_gobbledy_gook" /></td>
<td></td>
</tr>
<tr>
<td><input name="blnChecked[71_20]" type="checkbox" value="1" id="some_more_unusable_gobbledy_gook" /></td>
<td></td>
</tr>
<tr>
<td><input name="blnChecked[70_25]" type="checkbox" value="1" id="some_further_unusable_gobbledy_gook" /></td>
<td></td>
</tr>
</table>
<button type="button" id="btn">Click Me</button>

JavaScript onBlur for multiple fields

I have a table that consists of many text input fields which the user can assign values to. My goal is that if the user "onBlur"s any of the fields then a function will activate. I could resolve the issue by marking each cell individually, however it would be very repetitive and i'm sure there's a more efficient way around this.
To demonstrate:
<table>
<tr>
<td>I</td>
<td><input type="text" id="whatever1"></td>
</tr>
<tr>
<td>Love</td>
<td><input type="text" id="whatever2"></td>
</tr>
<tr>
<td>Stack Overflow</td>
<td><input type="text" id="whatever3"></td>
</tr>
</table>
With JS:
var e1 = document.getElementById('whatever1');
e1.onblur = alias;
function alias() {
alert('started');
}
and then repeat this for each input box another 2 times. Or hopefully there's an easier way.
You can delegate the event and put a listener on a containing element:
var e1 = document.getElementById('containing-table');
e1.addEventListener('blur', function(e){
alert(e.target);
}, true);
and the modified html:
<table id="containing-table">
<tr>
<td>I</td>
<td><input type="text" id="whatever1"></td>
</tr>
<tr>
<td>Love</td>
<td><input type="text" id="whatever2"></td>
</tr>
<tr>
<td>Stack Overflow</td>
<td><input type="text" id="whatever3"></td>
</tr>
</table>
here's a fiddle: http://jsfiddle.net/oj2wj1d6/7/
The advantage of this is that you can actually remove and add input elements and the listener will capture events on new nodes. You can add conditional statements inside of the function in addEventListener in order to further filter how you would want to respond to different types of event targets.
with jQuery, you could do something as simple as:
$("table").on("blur", "input", function(e){
alert(e.target);
});
Some useful documentation to learn more:
The blur event, scroll down for details about event delegation.
addEventListener.
more about doing event delegation in vanilla JS
<table>
<tr>
<td>I</td>
<td><input class="blurMe" type="text" id="whatever1"></td>
</tr>
<tr>
<td>Love</td>
<td><input class="blurMe" type="text" id="whatever2"></td>
</tr>
<tr>
<td>Stack Overflow</td>
<td><input class="blurMe" type="text" id="whatever3"></td>
</tr>
</table>
Then in javascript
//inputs as NodeList
var inputs = document.querySelectorAll(".blurMe");
//Convertion to Array
var inputsArr = Array.prototype.slice.call(input);
// Loop to asign event
inputsArr.forEach(function(item){
item.onBlur = alias;
});
Add a common class to all your element and use this for select all element getElementByClassname. if you want see exact what if your curent element add parameter event your function. and e.target give you DOM element.
how about this ?
<script>
document.getElementById()
var arr = document.getElementsByClassName('whatever');
for(var i=0;i<arr.length;i++)
{
arr[i].onblur=alias;
}
function alias() {
alert('started');
}
</script>
<table>
<tr>
<td>I</td>
<td><input type="text" class="whatever"></td>
</tr>
<tr>
<td>Love</td>
<td><input type="text" class="whatever"></td>
</tr>
<tr>
<td>Stack Overflow</td>
<td><input type="text" class="whatever"></td>
</tr>
</table>

Multiply value of text fields with the same class dynamically using another input box

I have the following form that is created on the fly using Coldfusion. The different inputs all have different values when loaded, but share the same class.
I will have another input field with a unique identifier - #permup
The form is as follows (form tag stripped):
<table width="100%" border="0" cellpadding="0" cellspacing="0" id="county-table" style="margin-top: 15px;">
<tr>
<TD>Length</TD>
<TD align="center">PerM</TD>
</tr>
<tr bgcolor="#ffffff">
<TD>from 1-10m</TD>
<TD align="center"><input class="perm" type="text" name="PerM1" value="1.60" size="6" /></TD>
</tr>
<tr bgcolor="#efefef">
<TD>from 11-20m</TD>
<TD align="center"><input class="perm" type="text" name="PerM2" value="1.10" size="6" /></TD>
</tr>
<tr bgcolor="#ffffff">
<TD>from 21-50m</TD>
<TD align="center"><input class="perm" type="text" name="PerM3" value="1.50" size="6" /></TD>
</tr>
<tr bgcolor="#efefef">
<TD>from 51-80m</TD>
<TD align="center"><input class="perm" type="text" name="PerM4" value="1.55" size="6" /></TD>
</tr>
<tr bgcolor="#ffffff">
<TD>from 81-150m</TD>
<TD align="center"><input class="perm" type="text" name="PerM5" value="1.10" size="6" /></TD>
</tr>
<tr bgcolor="#efefef">
<TD>from 151-200m</TD>
<TD align="center"><input class="perm" type="text" name="PerM6" value="1.10" size="6" /></TD>
</tr>
<tr>
<td> </td>
<td><input id="permup" type="text" name="permup" value="0" size="6" /></td>
</tr>
</table>
What I need is that when someone types the base rate increase in the #permup field, the fields with the class .perm have all their values increased by that amount, and if someone then sets the #permup field to 0 (zero) the fields with .perm are set back to their original value.
This has to work with JQuery on the class name as the table rows could be any number. I have the following script:
<script language="JavaScript" type="text/javascript">
$('#permup').keyup( function() {
$('.perm').each(function(){
var defaultValue = $(this).val();
$(this).val( $('#permup').val() * defaultValue );
});
});
</script>
It kind of works, but sets every value the same in the .perm fields and also does weird stuff when the field #perm is clicked out of or set to zero.
I hope someone can help!!
Many thanks
JS
As others have said you need to make sure you are doing math with numbers and not the default "value" given by the .value property. Also it is not advisable to store values in your display as you run into issues on how to retrieve an old value once you modify it. Below is code that does what you want and keeps track of the original values.
<script language="JavaScript" type="text/javascript">
// Store default values
var perm_items = document.getElementsByClassName("perm");
var orig_perm_values = new Array(perm_items.length);
for (var i = perm_items.length - 1; i >= 0; i--)
{
orig_perm_values[i] = perm_items[i].value;
document.getElementById('out').innerHTML = orig_perm_values[i];
}
function updateValues(event)
{
for (var i = perm_items.length - 1; i >= 0; i--)
{
perm_items[i].value = (parseFloat(orig_perm_values[i]) + parseFloat(event.target.value)).toFixed(2);
}
}
</script>
Try using parseFloat() and use keyup and focus event as shown :-
$('#permup').on('keyup focus', function() {
$('.perm').each(function(){
var defaultval = $('#permup').val();
var myValue;
if(defaultval == "0"){
myValue = $(this).attr('value')
}
else{
myValue = parseFloat( parseFloat($(this).attr('value')) * parseFloat(defaultval) ) || $(this).attr('value')
}
$(this).val( myValue );
});
});
DEMO
Side Note :- Always try to use parseInt() or parseFloat() while dealing in numbers in javascript/jquery otherwise numbers are also treated as string.

Categories