I have a project where I'm adding values from an attribute (comma separated integers) on a particular cell in each row of a table to an array in JS.
I know that if I create an array called myArray, then use myArray.push(121840,121841); the myArray.length result would be 2. This is what I expected. I had assumed (incorrectly) that since the value of the numbers attribute was the same format, e.g.: numbers="121840,121841", then the result would be the same using myArray.push($(this).attr('numbers'));, but I was mistaken as the length of that array is 1, instead of 2.
See below an example of what I'm trying to do and the issue I'm encountering.
Given a table like this where I'm grabbing the values from the last cell's numbers attribute:
<table border="1" width="100%">
<tbody emp-id="02" class="" name="Steve Smith">
<tr>
<td colspan="4">Steve Smith</td>
</tr>
<tr>
<td></td>
<td>2</td>
<td></td>
<td class="total" numbers="121856,121860">2</td>
</tr>
</tbody>
<tbody emp-id="01" name="Marky Mark">
<tr>
<td colspan="4">Marky Mark</td>
</tr>
<tr>
<td>1</td>
<td></td>
<td>1</td>
<td class="total" numbers="121840,121841">2</td>
</tr>
</tbody>
</table>
My JS would is:
$('table tbody tr').each(function() {
$(this).find('td:last').each(function(){
if ($(this).attr('numbers')) {
numbers.push($(this).attr('numbers'));
names.push($(this).parents("tbody").attr('name'));
}
});
});
In the above example, the array has the correct number values stored, (121856,121860,121840,12184), but the length is given as 2 as each cell's values was added as a single element, such that number[0]=121856,121860, instead of 121856.
How would I correct this so that each integer within the attribute is added as a single element?
JSFiddle: http://jsfiddle.net/jacbhg0n/3/
Any help would be greatly appreciated.
You can simply achieve that by splitting the numbers attribute string by using String.split() method while pushing it into the numbers array.
Live Demo :
const numbers = [];
const names = [];
$('table tbody tr').each(function() {
$(this).find('td:last').each(function(){
if ($(this).attr('numbers')) {
numbers.push($(this).attr('numbers').split(','));
names.push($(this).parents("tbody").attr('name'));
}
});
});
console.log(numbers.flat());
<table border="1" width="100%">
<tbody emp-id="02" class="" name="Steve Smith">
<tr>
<td colspan="4">Steve Smith</td>
</tr>
<tr>
<td></td>
<td>2</td>
<td></td>
<td class="total" numbers="121856,121860">2</td>
</tr>
</tbody>
<tbody emp-id="01" name="Marky Mark">
<tr>
<td colspan="4">Marky Mark</td>
</tr>
<tr>
<td>1</td>
<td></td>
<td>1</td>
<td class="total" numbers="121840,121841">2</td>
</tr>
</tbody>
</table>
Related
I have a data table that has a structure like:
<tbody>
<tr>
<td>ABC<td>
<td id="invNumbers0">DEF<td>
</tr>
<tbody>
<tr>
<td>GHI<td>
<td id="invNumbers1">JKL<td>
</tr>
<tr>
<td>MNO<td>
<td id="invNumbers2">PQR<td>
</tr>
<tr>
<td>STU<td>
<td id="invNumbers3">WXY<td>
</tr>
I want to find the value of all the elements whose id starts with "invNumbers"
I have tried:
alert($('[id^=invNumbers]').value);
alert($('[id^=invNumbers]').val());
Your table HTML structure is currently not valid as you need to enclosed tbody's within the table and you are missing closing tags of td's as well.
In addition, to get the text whose id starts with "invNumbers" you need to use jQuery .text() function not .val()
Edit: Since you want them separated by space or commas. Ideally in that case you can use .each function to get each of text separately so that you can do whatever you want with each text individually.
Live Working Demo:
$('[id^=invNumbers]').each(function(x, o) {
console.log($(o).text()) //showing each id text seperately
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tbody>
<tr>
<td>ABC</td>
<td></td>
<td id="invNumbers0">DEF</td>
<td></td>
</tr>
</tbody>
<tbody>
<tr>
<td>GHI</td>
<td></td>
<td id="invNumbers1">JKL</td>
<td></td>
</tr>
<tr>
<td>MNO</td>
<td></td>
<td id="invNumbers2">PQR</td>
<td></td>
</tr>
<tr>
<td>STU</td>
<td></td>
<td id="invNumbers3">WXY</td>
<td></td>
</tr>
</tbody>
</table>
I have a simple table and I want to sum two comlumns. On top of than only when a relevant checkbox is checked.
The table is like that
<table id="Zinzino" style="border-collapse: collapse; width: 100%;" border="1">
<tbody>
<tr>
<th><strong>Název</strong></th>
<th class="sum"><strong>První balíček</strong></th>
<th class="sum"><strong>Měsíčně</strong></th>
<th> </th>
</tr>
<tr>
<td>BalanceOil <input type="checkbox" id="BalanceOil" name="BalanceOil" class="beru"></td>
<td>149 EUR</td>
<td>30 EUR</td>
<td> </td>
</tr>
<tr>
<td>Extend (2x)<input type="checkbox" </td>
<td>44 EUR</td>
<td>22 EUR</td>
<td> </td>
</tr>
<tr>
<td>Zinobiotic (3x)<input type="checkbox" </td>
<td>64 EUR</td>
<td>23 EUR</td>
<td> </td>
</tr>
<tr>
<td><strong>Celkem</strong></td>
<td class="celkem"> </td>
<td class="celkem"> </td>
<td> </td>
</tr>
</tbody>
</table>
I can modify the hmtl if needed. I have a working fiddle solution Because I have not found anything working out of the box I coded this one. I am sure that someone could provide us with something more elegant. Or even correct my code.
This should do it. Feel free to ask if some detail is not understood.
$("input[type='checkbox']").on('change', function() {
updateTotals();
});
function updateTotals() {
// loop cells with class 'celkem'
$('.total').each(function(){
// for each total, get the column
const column = $(this).index();
let total = 0;
// loop trough all table rows, except the header and the row of totals
$(this).closest('table').find('tr:not(:first, :last)').each(function(){
if($(this).find('input').is(':checked')) {
// if the input is checked, add the numeric part to the total
const str = $(this).find(`td:eq(${column})`).text().replace(/\D/g, "");
if(str) {
total += Number(str);
}
}
});
if(!total) {
// if the total is zero, clear the cell
$(this).text("");
} else {
// otherwise, print the total for this column in the cell
$(this).text(total + " EUR");
}
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border="1" width="100%">
<tr>
<th>Col 1</th>
<th><strong>Col 2</strong></th>
<th><strong>Col 3</strong></th>
</tr>
<tr>
<td><input type="checkbox"></td>
<td>149 EUR</td>
<td>30 EUR</td>
</tr>
<tr>
<td><input type="checkbox"></td>
<td>44 EUR</td>
<td>22 EUR</td>
</tr>
<tr>
<td><input type="checkbox"></td>
<td>64 EUR</td>
<td>23 EUR</td>
</tr>
<tr>
<td><strong>Totals</strong></td>
<td class="total"> </td>
<td class="total"> </td>
</tr>
</table>
OK, I completed my solution which can be seen as an "almost One-Liner" in Vanilla JavaScript. Because of its brevity the readybility is slightly impaired.
In the second line the array trs is filled with all table rows (trs) with checked boxes. Only if something was checked (i.e. trs.length is "truthy") the calculation of sums is started in the following lines, otherwise sums is set to false. The "calculation" consists of a two-stage .map()-process (resulting in a 2D Array with all the individual prices) and a subsequent .reduce() call to do the summation for each column. A .forEach() is used internally here to do the summation for each of the relevant columns (not the first and the last ones).
In the last two lines the reults are written back to the table (last table record). Here the trenary operator ( ? : ) carefully checks whether sums is "truthy" before attemping the concatenation of sums[j]+" EUR".
document.getElementById("Zinzino").addEventListener('change',function(ev){
const trs=[...document.querySelectorAll("tbody tr")].filter(tr=>tr.querySelector(':checked'));
const sums=trs.length // calculate only when boxes were checked ...
? trs.map(tr=>[...tr.children].slice(1,-1) // NOT first and last columns
.map(td=>parseInt(td.textContent))) // 2D array of prices
.reduce((a,c)=>(a.forEach((dum,j)=>a[j]+=c[j]),a) ) // summation for each column
: false; // -> no calculation
// put results into last table row:
[...document.querySelectorAll("tbody tr:last-child td")].slice(1,-1)
.forEach((td,j)=>td.textContent=sums ? sums[j]+" EUR" :'' );
})
<table id="Zinzino" style="border-collapse: collapse; width: 100%;" border="1">
<thead><tr>
<th><strong>Název</strong></th>
<th class="sum"><strong>První balíček</strong></th>
<th class="sum"><strong>Měsíčně</strong></th>
<th> </th>
</tr></thead>
<tbody>
<tr>
<td>BalanceOil <input type="checkbox" id="BalanceOil" name="BalanceOil" class="beru"></td>
<td>149 EUR</td>
<td>30 EUR</td>
<td> </td>
</tr>
<tr>
<td>Extend (2x)<input type="checkbox"></td>
<td>44 EUR</td>
<td>22 EUR</td>
<td> </td>
</tr>
<tr>
<td>Zinobiotic (3x)<input type="checkbox"></td>
<td>64 EUR</td>
<td>23 EUR</td>
<td> </td>
</tr>
<tr>
<td><strong>Celkem</strong></td>
<td class="celkem"> </td>
<td class="celkem"> </td>
<td> </td>
</tr>
</tbody>
</table>
I want to select all first td values using JQuery.
Here is my code:
<tr id="#ASPxGridView1_DXHeadersRow0">
<td id="ASPxGridView1_col0" class="dxgvHeader" onmousedown="ASPx.GHeaderMouseDown('ASPxGridView1', this, event);" style="border-top-width:0px;border-left-width:0px;">
<table style="width:100%;">
<tbody>
<tr>
<td>Status</td>
<td style="width:1px;text-align:right;"><span class="dx-vam"> </span></td>
</tr>
</tbody>
</table>
</td>
<td id="ASPxGridView1_col1" class="dxgvHeader" onmousedown="ASPx.GHeaderMouseDown('ASPxGridView1', this, event);" style="border-top-width:0px;border-left-width:0px;">
<table style="width:100%;">
<tbody>
<tr>
<td>Worksheet ID</td>
<td style="width:1px;text-align:right;"><span class="dx-vam"> </span></td>
</tr>
</tbody>
</table>
</td>
</tr>
I want to get only 2 td (Status.Worksheet ID) elements from my above code using JQuery
You can pass any valid CSS selector to JQuery, so all you need is:
$("td:first-child");
// This will find and group together all the `<td>` elements that are the first ones
// within their parent (<tr>).
var $results = $("td:first-child");
// You can loop over the set and work with the individual DOM elements...
$results.each(function(index, result){
// result is the DOM element we're looping over
console.log(result.textContent);
});
// Or, you can access a specific element by index:
console.log($results[0].textContent + ", " + $results[1].textContent);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<tr id="#ASPxGridView1_DXHeadersRow0">
<td id="ASPxGridView1_col0" class="dxgvHeader" onmousedown="ASPx.GHeaderMouseDown('ASPxGridView1', this, event);" style="border-top-width:0px;border-left-width:0px;"><table style="width:100%;">
<tbody>
<tr>
<td>Status</td>
<td style="width:1px;text-align:right;"><span class="dx-vam"> </span></td>
</tr>
</tbody>
</table>
</td>
<td id="ASPxGridView1_col1" class="dxgvHeader" onmousedown="ASPx.GHeaderMouseDown('ASPxGridView1', this, event);" style="border-top-width:0px;border-left-width:0px;">
<table style="width:100%;">
<tbody>
<tr>
<td>Worksheet ID</td>
<td style="width:1px;text-align:right;"><span class="dx-vam"> </span></td>
</tr>
</tbody>
</table>
</td>
</tr>
I have a dropdown select menu with various options (i.e. 5, 10, 15, 20...) that represents # of computers. The default select menu value is 5. I am using some js to multiply the dropdown selection by an amount (i.e. 10) and populates a table td with a class of .price-1. So, for example if the user leaves the default selection of 5, the calculated value of .price-1 is 50.
This is working fine.
However, I then need to sum .price-1 with a few other <td> classes (i.e. .price-2, .price-3, .price-4...) to get a grand total in $ values that shows in #result.
How can I use js or jQuery to sum these td classes to get the grand total?
Below is my html of my table I need to sum.
<table id="tableOrderTotal" class="table tableTotal">
<tbody>
<tr>
<td>Item1</td>
<td class="price-1">calculated amount populated here</td>
</tr>
<tr>
<td>Item2</td>
<td class="price-2">calculated amount populated here</td>
</tr>
<tr>
<td>Item3</td>
<td class="price-3">13</td>
</tr>
<tr>
<td>Item3</td>
<td class="price-4">30</td>
</tr>
<tr class="summary">
<td class="totalOrder">Total:</td>
<td id="result" class="totalAmount"> </td>
</tr>
</tbody>
</table>
Get all td elements either using attribute value contains selector or by second td element of tr using :nth-child(). Now iterate over them using each() method and get sum using the text inside.
var sum = 0;
$('td[class*="price-"]').each(function() {
sum += Number($(this).text()) || 0;
});
$('#result').text(sum);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="tableOrderTotal" class="table tableTotal">
<tbody>
<tr>
<td>Item1</td>
<td class="price-1">calculated amount populated here</td>
</tr>
<tr>
<td>Item2</td>
<td class="price-2">calculated amount populated here</td>
</tr>
<tr>
<td>Item3</td>
<td class="price-3">13</td>
</tr>
<tr>
<td>Item3</td>
<td class="price-4">30</td>
</tr>
<tr class="summary">
<td class="totalOrder">Total:</td>
<td id="result" class="totalAmount"></td>
</tr>
</tbody>
</table>
With Array#reduce method as #rayon suggested.
$('#result').text([].reduce.call($('td[class*="price-"]'), function(sum, ele) {
return sum + (Number($(ele).text()) || 0);
}, 0));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="tableOrderTotal" class="table tableTotal">
<tbody>
<tr>
<td>Item1</td>
<td class="price-1">calculated amount populated here</td>
</tr>
<tr>
<td>Item2</td>
<td class="price-2">calculated amount populated here</td>
</tr>
<tr>
<td>Item3</td>
<td class="price-3">13</td>
</tr>
<tr>
<td>Item3</td>
<td class="price-4">30</td>
</tr>
<tr class="summary">
<td class="totalOrder">Total:</td>
<td id="result" class="totalAmount"></td>
</tr>
</tbody>
</table>
jQuery Object has a direct attribute referring to the number of the matched elements.
var sum = $('td[class*="price-"]').length;
$('#result').text(sum);
I have a table with the following structure:
<table>
<tr>
<td>some column|1</td>
<td id="abc|1">abc</td>
<td id="abc|1">abc</td>
</tr>
<tr>
<td>another column|1</td>
<td id="def|1">def</td>
<td id="def|1">def</td>
</tr>
<tr>
<td>ome column|2</td>
<td id="abc|2">abc</td>
<td id="abc|2">abc</td>
</tr>
<tr>
<td>another column|2</td>
<td id="def|2">def</td>
<td id="def|2">def</td>
</tr>
</table>
The content comes from a database.
As you can see, the IDs have the suffix |x. I want to remove all elements with the suffix |2 in the 2nd column and all elements with the suffix |1 in the 3rd column.
Also the 3rd column should be shifted to the top, and all rows ending with |2 in the 1st column should disappear.
So that the final result looks like that:
<table>
<tr>
<td>some column|1</td>
<td id="abc|1">abc</td>
<td id="abc|2">abc</td>
</tr>
<tr>
<td>another column|1</td>
<td id="def|1">def</td>
<td id="def|2">def</td>
</tr>
</table>
This is my approach, but it doesn't work at all:
$("table td:nth-child(2)").find("[id$=2]").each(function() {
$(this).hide();
});
$("table td:nth-child(3)").find("[id$=1]").each(function() {
$(this).hide();
});
Here is the fiddle.
ID should be unique. It's better if you can change the HTML and make IDs unique.
IF CHANGING HTML IS NOT POSSIBLE
As both the selector are pointing to same element, use following
$("table td:nth-child(2)[id$=2], table td:nth-child(3)[id$=1]").hide();
Demo