I have table as follows :
<table>
<thead>
<th>PRODUCT</th>
<th>QUANTITY</th>
<th>AREA</th>
<th>PRICE</th>
<th>TOTAL</th>
<tr>
<td id="name">SWEETS</td>
<td id="qty">10</td>
<td id="area">250</td>
<td id="price">16.50</td>
<td id="total">160.50</td>
</tr>
<tr>
<td id="name"">DRY FOODS</td>
<td id="qty">5</td>
<td id="area">100</td>
<td id="price">10.25</td>
<td id="total">51.25</td>
</tr>
<tr>
<td id="name">FRESH</td>
<td id="qty">20</td>
<td id="area">250</td>
<td id="price">5</td>
<td id="total">100</td>
</tr>
<tr>
<td id="name">MEAT</td>
<td id="qty">10</td>
<td id="area">250</td>
<td id="price">15</td>
<td id="total">150</td>
</tr>
<tr>
<td id="name">FROZEN</td>
<td id="qty">20</td>
<td id="area">300</td>
<td id="price">10</td>
<td id="total">200</td>
</tr>
</table>
So, I want to make an array like {area:total} then grouping array values based on area and sum area values.
Like :
AREA 250 : 410.5
AREA 100 : 51.25
AREA 300 : 200
I tried as follow which I got it array but I don't know how can I grouping the areas ( I used setInterval function because employees can remove or change the area values)
setInterval(function() {
var $row = $(this).closest("tr");
var sasData = [];
$row.each(function(i) {
var sasValue = parseFloat($row.find("#area").val());
var totValue = parseFloat($row.find("#total").val());
sasData.push({sas:sasValue, tot:totValue});
console.log(sasData);
});
function compressedArray(original) {
var compressed = [];
};
}, 1500)
Could you please show me the way how can we handle this issue?
This JSFiddle should solve your problem. I've also fixed your missing thead, your double quote in the DRY FOODS td, and changes id's to classes:
http://jsfiddle.net/Q9nrf/1/
var areas = {};
$("tr").each(function() {
var area = $(this).find("td.area").text();
if (area != "") {
var total = parseFloat($(this).find("td.total").text());
if (!areas.hasOwnProperty(area)) {
areas[area] = 0;
}
areas[area] += total;
}
});
console.log(areas);
You will need to change the id values to some other attribute, say class.
Loop over the rows (use the tbody element to skip the header) and collect values from the elements with the classes you're after. You will need to use an array to store them, as you can't order the properties of an object and each property must have a unique name.
id should be unique. so change <td id="area">250</td> to <td class="area">250</td>
then just call:
o = {};
$("td.area").each(function(){
key = o[$(this).text()];
if (!key) key = 0;
key += parseFloat( $(this).closest("tr").find(".total").text());
});
then you have on object contains key-value [key=area code, value=total]
Related
No jQuery involve pls. I am just started learning javascript.
I want to find the class='id' of the table when I clicked on the class='detail' button.
I manage to point to class='id' but I can't get the value out of it, why?
var button = document.getElementsByClassName("detail");
for (var i in button) {
button[i].onclick = function() {
var row = this.closest("tr");
var id = row.getElementsByClassName("id");
var value = id.innerText;
console.log(id);
console.log(value); //show undefined here
}
}
<table>
<tbody>
<tr>
<td class="id">123</td>
<td class="name">abc</td>
<td><button class="detail">detail</button></td>
</tr>
<tr>
<td class="id">456</td>
<td class="name">def</td>
<td><button class="detail">detail</button></td>
</tr>
</tbody>
</table>
where would need to change? I must use class here, as the table generated through javascript. thanks.
getElementsByClassName returns HTMLCollection containing multiple matching elements. Like an array, you can access the first element in the collection with [0]
var button = document.getElementsByClassName("detail");
for (var i in button) {
button[i].onclick = function () {
var row = this.closest("tr");
var id = row.getElementsByClassName("id");
var value = id[ 0 ].innerText;
console.log(id);
console.log(value);
}
}
<table>
<tbody>
<tr>
<td class="id">123</td>
<td class="name">abc</td>
<td><button class="detail">detail</button></td>
</tr>
<tr>
<td class="id">456</td>
<td class="name">def</td>
<td><button class="detail">detail</button></td>
</tr>
</tbody>
</table>
I have a table with following rows and cells:
<table id='table1'>
<tr id='row1'>
<th>index</th>
<th>Product</th>
<th>Description</th>
</tr>
<tr id='row2' name='row'>
<td name='index'>1</td>
<td name='product'>Apples</td>
<td name='description'>fruits</td>
</tr>
<tr id='row3' name='row'>
<td name='index'>2</td>
<td name='product'>Bananas</td>
<td name='description'>fruits</td>
</tr>
<tr id='row4' name='row'>
<td name='index'>3</td>
<td name='product'>Carrots</td>
<td name='description'>vegetables</td>
</tr>
<tr id='row5' name='row'>
<td name='index'></td>
<td name='product'></td>
<td name='description'></td>
</tr>
</table>
I need to select the value for the last td with name='index' which is not null. Anyone has any idea how can this be done.
Use the following selector :
$('td[name=index]:not(:empty):last')
For purely educational purposes, here is a non jQuery version:
function getLastNonEmptyCell(tableSelector) {
//Find parent table by selector
var table = document.querySelector(tableSelector)
//Return null if we can't find the table
if(!table){
return null;
}
var cells = table.querySelectorAll("td")
var lastNonEmptyCell = null;
//Iterate each cell in the table
//We can just overwrite lastNonEmptyCell since it's a synchronous operation and the return value will be the lowest item in the DOM
cells.forEach(function(cell) {
//!! is used so it's so if it is not null, undefined, "", 0, false
//This could be changed so it's just cell.innerText.trim() !== ""
if (!!cell.innerText) {
lastNonEmptyCell = cell;
}
})
return lastNonEmptyCell;
}
var cell = getLastNonEmptyCell("#table1")
Edit
As #squint suggested this can be done much more succintly:
function lastNonEmptyCell(tableSelector) {
//Since we want the last cell that has content, we get the last-child where it's not empty. This returns the last row.
var row = document.querySelectorAll(tableSelector + " td:not(:empty):last-child")
//Just grabbing the last cell using the index
return row[row.length - 1]
}
I have the following table:
<table>
<tr>
<th>Category</th>
<th>Value</th>
</tr>
<tr>
<td class="cat1">cat1</td>
<td class="value">123</td>
</tr>
<tr>
<td class="cat2">cat2</td>
<td class="value">356</td>
</tr>
<tr>
<td class="cat1">cat1</td>
<td class="value">486</td>
</tr>
</table>
I need a way to add/sum all values grouped by category, ie: add/sum all values in cat1, then add/sum all values in cat2. For each group I will do something with the total.
So I was hoping for something like:
for each unique category:
sum values in category
do something with this category total
For cat1 the total would be 123 + 486. Cat2 would just be 356. And so on if there were more categories.
I would prefer a purely javascript solution, but JQuery will do if that's not possible.
If I understand you correctly, you do a repeat of each td:first-child (The category cell).
Create a total object. You can check if the category is exist in it for each cell. If so, add current value to the stored value. If not, insert new property to it.
Like this:
var total = {};
[].forEach.call(document.querySelectorAll('td:first-child'), function(td) {
var cat = td.getAttribute('class'),
val = parseInt(td.nextElementSibling.innerHTML);
if (total[cat]) {
total[cat] += val;
}
else {
total[cat] = val;
}
});
console.log(total);
<table>
<tr>
<th>Category</th>
<th>Value</th>
</tr>
<tr>
<td class="cat1">cat1</td>
<td class="value">123</td>
</tr>
<tr>
<td class="cat2">cat2</td>
<td class="value">356</td>
</tr>
<tr>
<td class="cat1">cat1</td>
<td class="value">486</td>
</tr>
</table>
Here's a simple approach using only javascript
//grab data
var allTR = document.getElementsByTagName('TR');
var result = {};
//cycle table rows
for(var i=0;i<allTR.length;i+2){
//read class and value object data
var class = allTR[i].getAttribute('class');
var value = allTR[i+1].innerText;
//check if exists and add, or just add
if(result[class])
result[class] += parseInt(value);
else
result[class] = parseInt(value);
}
You have to use getElementsByTagName("td"); to get all the <td> collection and then you need to loop through them to fetch their innerText property which later can be summed up to get the summation.
Here is the working Fiddle : https://jsfiddle.net/ftordw4L/1/
HTML
<table id="tbl1">
<tr>
<th>Category</th>
<th>Value</th>
</tr>
<tr>
<td class="cat1">cat1</td>
<td class="value">123</td>
</tr>
<tr>
<td class="cat2">cat2</td>
<td class="value">356</td>
</tr>
<tr>
<td class="cat1">cat1</td>
<td class="value">486</td>
</tr>
<tr>
<td class="total"><b>Total</b></td>
<td class="totalValue"></td>
</tr>
</table>
Javascript
var tds=document.getElementsByTagName("td");
var total=0;
for (var i = 0; i<tds.length; i++) {
if (tds[i].className == "value") {
if(total==0) {
total = parseInt(tds[i].innerText);
} else {
total = total + parseInt(tds[i].innerText);
}
}
}
document.getElementsByClassName('totalValue')[0].innerHTML = total;
Hope this helps!.
here is a solution with jQuery :) if you are interested. it's pretty straightforward
var sumCat1 = 0;
var sumCat2 = 0;
$(".cat1 + .value").each(function(){
sumCat1 += parseInt($(this).text());
})
$(".cat2 + .value").each(function(){
sumCat2 += parseInt($(this).text());
})
console.log(sumCat1)
console.log(sumCat2)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<th>Category</th>
<th>Value</th>
</tr>
<tr>
<td class="cat1">cat1</td>
<td class="value">123</td>
</tr>
<tr>
<td class="cat2">cat2</td>
<td class="value">356</td>
</tr>
<tr>
<td class="cat1">cat1</td>
<td class="value">486</td>
</tr>
</table>
A simple approach in JQuery...
var obj = {};
$('tr').each(function() {
$this = $(this)
if ($this.length) {
var cat = $(this).find("td").first().html();
var val = $(this).find("td").last().html();
if (cat) {
if (!obj[cat]) {
obj[cat] = parseInt(val);
} else {
obj[cat] += parseInt(val);
}
}
}
})
console.log(obj)
I have a "football squares" game going, and I would like to highlight cells of the winners based on the top and side headers.
Now, I know they're not really headers but they serve the same purpose.
My table is located at this jfiddle: https://jsfiddle.net/8ybtntqg/
What I want to do is this:
Let's say the winner would be whoever is in the cell that lines up with TeamA - 2 and TeamZ - 9. That would be Mitch. I want to highlight Mitch's cell. How would I do this with Javascript or Jquery? I know how to do it if I was just looking for the word "Mitch", but I want to automatically do it, based on the numbers of TeamA and TeamZ.
I have this so far, but of course that only highlights the name but it's the only place I knew to start:
$('#table_id td').each(function() {
if ($(this).text() == 'Mitch') {
$(this).closest('td').css('background-color', '#f00');
}
});
You can get the index of the column and row using jQuery's filter() method.
That will give you direct access to the cell like so:
$('tr').eq(row).find('td').eq(col).css('background-color', '#f00');
Snippet:
function highlight(teamA, teamZ) {
var col, row;
col = $('#table_id td').filter(function() { //return column of teamA
return $(this).html() === teamA.replace(' - ', '<br>');
}).index();
row = $('#table_id tr').filter(function() { ////return row of teamZ
return $(this).html().indexOf(teamZ.replace(' - ', '<br>')) > -1;
}).index();
$('tr').eq(row).find('td').eq(col).css('background-color', '#f00');
}
highlight('TeamA - 2', 'TeamZ - 9');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="1" id="table_id">
<tr>
<td>Squares</td>
<td>TeamA<br>1</td>
<td>TeamA<br>2</td>
<td>TeamA<br>3</td>
<td>TeamA<br>4</td>
<td>TeamA<br>5</td>
<td>TeamA<br>6</td>
<td>TeamA<br>7</td>
<td>TeamA<br>8</td>
<td>TeamA<br>9</td>
<td>TeamA<br>0</td>
</tr>
<tr>
<td>TeamZ<br>3</td>
<td bgcolor="#89ff89">Mark</td>
<td bgcolor="#89ff89">John</td>
</tr>
<tr>
<td>TeamZ<br>5</td>
<td bgcolor="#89ff89">Mike</td>
<td bgcolor="#89ff89">Earl</td>
</tr>
<tr>
<td>TeamZ<br>8</td>
<td bgcolor="#89ff89">Morris</td>
<td bgcolor="#89ff89">Brice</td>
</tr>
<tr>
<td>TeamZ<br>7</td>
<td bgcolor="#89ff89">Taylor</td>
<td bgcolor="#89ff89">Evan</td>
</tr>
<tr>
<td>TeamZ<br>9</td>
<td bgcolor="#89ff89">Mandy</td>
<td bgcolor="#89ff89">Mitch</td>
</tr>
<tr>
<td>TeamZ<br>2</td>
<td bgcolor="#89ff89">Tony</td>
<td bgcolor="#89ff89">Jennifer</td>
</tr>
<tr>
<td>TeamZ<br>1</td>
<td bgcolor="#89ff89">Kristen</td>
<td bgcolor="#89ff89">Hector</td>
</tr>
<tr>
<td>TeamZ<br>4</td>
<td bgcolor="#89ff89">Gabby</td>
<td bgcolor="#89ff89">David</td>
</tr>
<tr>
<td>TeamZ<br>6</td>
<td bgcolor="#89ff89">George</td>
<td bgcolor="#89ff89">Steffanie</td>
</tr>
<tr>
<td>TeamZ<br>0</td>
<td bgcolor="#89ff89">Breck</td>
<td bgcolor="#89ff89">Terry</td>
</tr>
</table>
You can iterate over all the table elements to find the matching values, then use CSS selectors to highlight the matched field. Something like this will work:
winningAScore = 2;
winningZScore = 9;
//get top row
counter = 0;
$('#table_id tr:first-child td').each(function() {
var strOut = $(this).html().replace(/Team[A-z]<br>/g,'');
if(!isNaN(strOut) && strOut == winningAScore) {
posnX = counter;
}
counter++;
})
//get first column row
counter = 0;
$('#table_id tr td:first-child').each(function() {
var strOut = $(this).html().replace(/Team[A-z]<br>/g,'');
if(!isNaN(strOut) && strOut == winningZScore) {
posnY = counter;
}
counter++;
})
$('tr:eq('+posnY+') td:eq('+posnX+')').css('background-color', 'red');
You can see it working in this JS Fiddle: https://jsfiddle.net/igor_9000/8ybtntqg/1/
You can do index based detect and selection in jQuery like so: $('tr:eq(2) td:eq(1)').css('background-color', 'red');
Example: http://codepen.io/anon/pen/EPLNvB
Having such table
<table>
<thead> ... </thead>
<tbody>
<tr class="TableOdd">
<td class="TableCol0"> 1 </td>
<td class="TableCol1"> x </td>
<td class="TableCol2"> x </td>
<td class="TableCol3"> # </td>
</tr>
<tr class="TableEven">
<td>....</td>
</tr>
</tbody>
E.g. each cell has own class indicating it's column number TableCol0,1,2..N
In each row, needed compare the content of the cells in column 1 and 2 and write the result into colum3.
Managed the following script,
$(document).ready(function() {
var toterr = 0;
$('tbody tr.TableEven,tbody tr.TableOdd').each(function() {
var wanted = $(this).find('.TableCol1' ).html();
var actual = $(this).find('.TableCol2' ).html();
//console.log('wanted='+wanted+'=actual='+actual+'=');
if ( wanted == actual ) {
$(this).find('.TableCol3').text('ok');
} else {
$(this).find('.TableCol3').text('ERROR');
toterr++;
}
});
$('#totalerror').text(toterr);
});
It is probably not optimal, but works.
Now have a bit different scenario: Need compare two cells what are before a cell with a specified content (:CMP:), e.g:
<table>
<thead> ... </thead>
<tbody>
<tr class="TableOdd">
<td class="TableCol0"> x </td>
<td class="TableCol1"> x </td>
<td class="TableCol2"> :CMP: </td>
<td class="TableCol3"> etc </td>
</tr>
<tr class="TableEven">
<td class="TableCol0"> N </td>
<td class="TableCol1"> x </td>
<td class="TableCol2"> y </td>
<td class="TableCol3"> :CMP: </td>
</tr>
</tbody>
For each row, need compare cells what are before :CMP:, and replace the :CMP: with the result. e.g.
in the 1st row need compare the x and x and write ok in the cell .TableCol2
in the 2nd row need compare the x and y and write ERROR in the cell .TableCol3
I haven't idea how to modify the above script.
Can easily get the index of the cell that contains ':CMP:' and use the index to reference the previous cells. Or use traverses like prev() or use eq() once index is found.
$('tbody tr').each(function () {
var $cells = $(this).children(),
$cmp = $cells.filter(':contains(":CMP:")'),
cmpIndex = $cells.index($cmp);
// array of values of previous cells
var values = $.map($cells.slice(cmpIndex - 2, cmpIndex), function (el) {
return $.trim($(el).text());
});
// make sure we have 2 cells with values and compare
var cmpText = values.length === 2 && values[0] === values[1] ? 'OK' : 'ERROR';
$cmp.text(cmpText);
});
DEMO