Search the table by cell content with jquery and relative referencing - javascript

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

Related

How to select the last cell from table which is not null, using JQuery

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]
}

Highlight table cell based on vertical and horizontal headers

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

scan table data and replace certain string inside html table

I have following table
<table class="data">
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
</tr>
</thead>
<tbody>
<tr>
<td>
1 data
</td>
<td>
2 data
</td>
<td>
123456789123
</td>
</tr>
</tbody>
</table>
how can I dynamically scan table and replace only values in third table body td values where information like 123456789123 is stored.
This information should be placed with certain character on certain string location so
<td> 123456789123 </td> should be <td> 12345678*12* </td>
Please find below code block for your need, I have added one specific class to TD for which you want to modify value.
$( document ).ready(function() {
$('.value_td').each(function(key, ele){
// Getting Original Value
var original_val = $(ele).text().trim();
// You can change your logic here to modify text
var new_value = original_val.substr(0, 8) + '*' + original_val.substr(9, 2) + '*';
// Replacing new value
$(ele).text(new_value);
});
});
<table class="data">
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
</tr>
</thead>
<tbody>
<tr>
<td>
1 data
</td>
<td>
2 data
</td>
<td class="value_td">
123456789123
</td>
</tr>
</tbody>
</table>
JS Fiddle
To replace the selected texts by indexs, use this:
// replace the 'n'th character of 's' with 't'
function replaceAt(s, n, t) {
return s.substring(0, n) + t + s.substring(n + 1);
}
$('td:nth-of-type(3)').each(function(i, item){
$(this).text($(this).text().trim()); // remove extra spaces
$(this).text(replaceAt($(this).text(), 8, '*')); // replace character in position 8
$(this).text(replaceAt($(this).text(), 11, '*')); // replace character in position 11
});
See the working demo: https://jsfiddle.net/lmgonzalves/6ppo0xp3/
Try this:
$('.data td:nth-child(3n)').text('foo');
This will change every 3rd td’s text inside .data to foo. Here’s a demo: http://jsbin.com/katuwumeyu/1/edit?html,js,output
Let me know if that helps, I’ll gladly adapt my answer in case this isn’t what you need.
You can use jquery ":eq(2)" to track 3rd td position like this:
var el = $('table.data tbody tr td:eq(2)');
el.text(el.text().replace('123456789123','12345678*12*'));
https://jsfiddle.net/v25gu3xk/
or maybe you need to replace char positions:
var el = $('table.data tbody tr td:eq(2)');
var vl = el.text().trim();
el.text(vl.substr(0, 8) + '*' + vl.substr(9, 2) + '*');
https://jsfiddle.net/v25gu3xk/1/

Remove table row by finding content with clause

I have this code:
<table>
<tbody>
<tr><td>Table 1</td></tr>
</tbody>
</table>
<table>
<tbody>
<tr>
<td align="left">Number</td>
<td><b>33</b></td>
</tr>
<tr>
<td width="150" align="left">Field</td>
<td>XXXX</td>
</tr>
<tr>
<td align="left">Select: </td>
<td colspan="4">
<select name="status" size="1">
<option selected="selected" value="2">one</option>
<option value="1">two</option>
</select>
</td>
</tr>
</tbody>
</table>
and i want to remove this line by searching "Field" with pure Javascript:
<tr>
<td width="150" align="left">Field</td>
<td>XXXX</td>
</tr>
when there is a 33, 66 or 99 in this line from my 2nd table:
<tr>
<td align="left">Number</td>
<td>33</td>
</tr>
The problem is that i don't have any id's or classes for identification! i want to use the code with Greasemonkey.
Here you can see a JSFIDDLE of my table.
And here you can see on JSFIDDLE how it should look.
Best regards bernte
Here you go:
var disallowedValues = ['33', '66', '99'];
var cols = document.getElementsByTagName('td');
var colslen = cols.length;
var i = -1;
var disallowedTable;
while(++i < colslen){
// look for the td where the disallowed values are
if(disallowedValues.indexOf(cols[i].innerHTML) >= 0)
{
// get the table where the disallowed values is
disallowedTable = cols[i].parentNode.parentNode.parentNode;
// break the cicle to stop looking for other rows
//break;
}
}
// look for the 'Field' value only on the table that has the disallowed value
var cols = disallowedTable.getElementsByTagName('td');
cols = disallowedTable.getElementsByTagName('td');
colslen = cols.length;
i = -1;
while(++i < colslen){
// look for the td where the 'Field' value is
if(cols[i].innerHTML == 'Field')
{
// get the tr for such td
var deletionTR = cols[i].parentNode;
//delete that tr
deletionTR.parentNode.removeChild(deletionTR);
// break the cicle to stop looking for other rows
break;
}
}
You can always do a simpler version if jquery is an option.

Sum associative array key values and group it by key

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]

Categories