Get column name from row mapping with onClick handler - javascript

In this reactjs app I have a table with the following body:
<tbody>
{results.map(result =>
<tr key={result.metric} onClick={this.handleClick}>
<td className="inpt-td">{result.t00}</td>
<td className="inpt-td">{result.t01}</td>
<td className="inpt-td">{result.t02}</td>
<td className="inpt-td">{result.t03}</td>
<td className="inpt-td">{result.t04}</td>
<td className="inpt-td">{result.t05}</td>
<td className="inpt-td">{result.t06}</td>
<td className="inpt-td">{result.t07}</td>
<td className="inpt-td">{result.t08}</td>
<td className="inpt-td">{result.t09}</td>
<td className="inpt-td">{result.t10}</td>
<td className="inpt-td">{result.t11}</td>
<td className="inpt-td">{result.t12}</td>
<td className="inpt-td">{result.t13}</td>
<td className="inpt-td">{result.t14}</td>
<td className="inpt-td">{result.t15}</td>
<td className="inpt-td">{result.t16}</td>
<td className="inpt-td">{result.t17}</td>
<td className="inpt-td">{result.t18}</td>
<td className="inpt-td">{result.t19}</td>
<td className="inpt-td">{result.t20}</td>
<td className="inpt-td">{result.t21}</td>
<td className="inpt-td">{result.t22}</td>
<td className="inpt-td">{result.t23}</td>
</tr>
)}
</tbody>
The header does not exist for this particular table, but I was wondering if there was a way to obtain the column name of a clicked cell. So for example if you clicked on the second cell in a given row, it would return "t01", which is the column name.
My searches online did not provide an efficient way of doing this. Is there a method to retrieve this info?

In your handleClick you can get access to the event.target property, which is a cell.
After that you can do:
var child = event.target;
var parent = child.parentNode;
// equivalent of parent.children.indexOf(child)
var index = Array.prototype.indexOf.call(parent.children, child);
var value = 't' + index // this will be value what you are looking for
If you need information how to use event.target - here is an example.

Related

Change td background colour based on the value

I am using google table charts,value where the data is like :
<tr class="google-visualization-table-tr-even">
<td class="google-visualization-table-td">TC-206</td>
<td class="google-visualization-table-td">Customer logs in</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Fail</td><td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Pass</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Pass</td>
</tr>
<tr class="google-visualization-table-tr-odd">
<td class="google-visualization-table-td">TC-207</td>
<td class="google-visualization-table-td">Customer signs out</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Pass</td>
<td class="google-visualization-table-td">Pass</td>
</tr>
So the table value keeps on incrementing, that means, tr and td keeps increasing based on test executions and number of testcases.
So What I like to make a change is if the td value is Pass, the background colour should be green and if its fail, it should be red.
i tried like
var table1 = document.getElementsByClassName('google-visualization-table-td');
var key = table1.value;
for (key in table1) {
if(key != "Pass"){
key.bgColor='#800000';
}
};
But no luck !!
How its possible. Please help.
So as a caveat to doing it via the javascript way, you're already adding a style tag to each cell that will re-eval and paint each independently as you're say for example adding new rows etc that would also involve firing off that method each time.
Another option to consider is a css selector that doesn't need to be refired, and will handle the issue while not adding a new style tag to each cell which becomes something like an added attribute of data-whatever="<value>" vs style="background-color: <colorThatWillBeConvertedToRGBAutomatically>" to each cell.
So just a no js option;
// Nope.
[data-tag=Pass] {
background-color: green;
}
[data-tag=Fail] {
background-color: red;
}
<table>
<tr class="google-visualization-table-tr-even">
<td class="google-visualization-table-td" data-tag="TC-206">TC-206</td>
<td class="google-visualization-table-td" data-tag="Customer logs in">Customer logs in</td>
<td class="google-visualization-table-td" data-tag="Fail">Fail</td>
<td class="google-visualization-table-td" data-tag="Fail">Fail</td>
<td class="google-visualization-table-td" data-tag="Fail">Fail</td>
<td class="google-visualization-table-td" data-tag="Pass">Pass</td>
<td class="google-visualization-table-td" data-tag="Fail">Fail</td>
<td class="google-visualization-table-td" data-tag="Pass">Pass</td></tr>
<tr class="google-visualization-table-tr-odd">
<td class="google-visualization-table-td" data-tag="TC-207">TC-207</td>
<td class="google-visualization-table-td" data-tag="Customer signs out">Customer signs out</td>
<td class="google-visualization-table-td" data-tag="Fail">Fail</td>
<td class="google-visualization-table-td" data-tag="Fail">Fail</td>
<td class="google-visualization-table-td" data-tag="Fail">Fail</td>
<td class="google-visualization-table-td" data-tag="Fail">Fail</td>
<td class="google-visualization-table-td" data-tag="Pass">Pass</td>
<td class="google-visualization-table-td" data-tag="Pass">Pass</td></tr>
</table>
You are not using the right for loop.
Take a look at this documentation (MDN).
Also, using element.value will return the value of the attribute value, not the text content.
The following code should do the trick.
var elements = document.getElementsByClassName('google-visualization-table-td');
for (var i = 0; i < elements.length; i++) {
var value = elements[i].innerText || elements[i].textContent;
if (value === 'Fail') {
elements[i].style.backgroundColor = '#FF0000';
} else if (value === 'Pass') {
elements[i].style.backgroundColor = '#00FF00';
}
}
td {
display: block;
border: solid 1px #CCC;
}
<table>
<tr class="google-visualization-table-tr-even">
<td class="google-visualization-table-td">TC-206</td>
<td class="google-visualization-table-td">Customer logs in</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Fail</td><td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Pass</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Pass</td>
</tr>
<tr class="google-visualization-table-tr-odd">
<td class="google-visualization-table-td">TC-207</td>
<td class="google-visualization-table-td">Customer signs out</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Pass</td>
<td class="google-visualization-table-td">Pass</td>
</tr>
</table>
You can add a listener if user can add or remove items in the table or if yourself manage table you can just add this code to your managing functions like adding or removing:-
var x = document.getElementsByClassName("google-visualization-table-td");
for (i = 0; i < x.length; i++) {
if(x[i].innerText === 'Pass')
x[i].style.backgroundColor = "green";
else if(x[i].innerText === 'Fail')
x[i].style.backgroundColor = "red";
}
.forEach your HTMLTable.rows
.forEach your HTMLRow.cells
Get each cell content cell.textContent.trim().toLowerCase()
If the content is either pass|fail add a is-[pass|fail] classname
[...document.getElementById("google-visualization").rows].forEach( row =>
[...row.cells].forEach( cell => {
const cont = cell.textContent.trim().toLowerCase();
if (/^(pass|fail)$/.test(cont)) {
cell.classList.add(`is-${cont}`);
}
})
);
.is-pass{background: green;}
.is-fail{background: red;}
<table id="google-visualization">
<tr class="google-visualization-table-tr-even">
<td class="google-visualization-table-td">TC-206</td>
<td class="google-visualization-table-td">Customer logs in</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Pass</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Pass</td>
</tr>
<tr class="google-visualization-table-tr-odd">
<td class="google-visualization-table-td">TC-207</td>
<td class="google-visualization-table-td">Customer signs out</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Fail</td>
<td class="google-visualization-table-td">Pass</td>
<td class="google-visualization-table-td">Pass</td>
</tr>
</table>
Clearly the best way would be to assign a class fail or pass at elements creation and style using CSS, instead of using JS loops.

Highlight multiple rows in several tables

I have a page with several rows containing information, made by several users. I'm looking for a way to highlight the all the users rows on mouseover.
This "Highlight multiple items on hover's condition" almost solved my problem, but since the classes or id's in my problem are dynamic from a database, and would contain an identifier from the DB and are unique each time. I have not been able to apply it.
Example code: https://jsfiddle.net/3cehoh78/
<table class="testtable">
<tr id="uniqueIDthatcantbechanged">
<td class="cellclass">Line 1a</td>
<td class="cellclass">Sam</td>
<td class="cellclass">data</td>
</tr>
<tr id="uniqueIDthatcantbechanged">
<td class="cellclass">Line 2a</td>
<td class="cellclass">Frodo</td>
<td class="cellclass">data</td>
</tr>
<tr id="uniqueIDthatcantbechanged">
<td class="cellclass">Line 3a</td>
<td class="cellclass">Sam</td>
<td class="cellclass">data</td>
</tr>
<tr id="uniqueIDthatcantbechanged">
<td class="cellclass">Line 4a</td>
<td class="cellclass">Legoman</td>
<td class="cellclass">data</td>
</tr>
</table>
<br>
<br>
<table class="testtable">
<tr id="uniqueIDthatcantbechanged">
<td class="cellclass">Line 1b</td>
<td class="cellclass">Sauron</td>
<td class="cellclass">data</td>
</tr>
<tr id="uniqueIDthatcantbechanged">
<td class="cellclass">Line 2b</td>
<td class="cellclass">Sam</td>
<td class="cellclass">data</td>
</tr>
<tr id="uniqueIDthatcantbechanged">
<td class="cellclass">Line 3b</td>
<td class="cellclass">Sam</td>
<td class="cellclass">data</td>
</tr>
<tr id="uniqueIDthatcantbechanged">
<td class="cellclass">Line 4b</td>
<td class="cellclass">Legoman</td>
<td class="cellclass">data</td>
</tr>
<tr id="uniqueIDthatcantbechanged">
<td class="cellclass">Line 5b</td>
<td class="cellclass">Frodo</td>
<td class="cellclass">data</td>
</tr>
</table>
In this example, I want all the rows with "Sam" to be highlighted on mouseover on one of them, so rows 1a,3a,2b,3b.
I was thinking of adding a class to all the Sam rows when generating the tables (Sam has a unique user ID), but how do I then change css that affects all the rows on mouseover (and not just one).
Please note that I cant pre-add css classes for all the unique userID's, this is just an example.
Here a solution with JQuery https://jsfiddle.net/3cehoh78/5
$(document).ready(function() {
$( "tr" ).hover(function() {
var search = $(this).find("td:eq(1)").text();
$( ".highlight" ).removeClass("highlight");
$("tr:contains('"+search+"')").addClass("highlight");
}); /* END HOVER */
}); // end document ready
Simple solution without using jQuery and co: https://jsfiddle.net/3cehoh78/3/
var rows = [].slice.call(document.querySelectorAll('.testtable tr'));
rows.forEach(function(row) {
row.addEventListener('mouseover', function() {
resetHighlighting();
var name = row.querySelector('td:nth-child(2)').textContent;
rows.forEach(function(r) {
if (r.querySelector('td:nth-child(2)').textContent === name) {
r.classList.add('highlighted');
}
});
});
});
function resetHighlighting() {
rows.forEach(function(row) {
row.classList.remove('highlighted');
});
}
Here's another way using vanilla-JavaScript.
var tds = document.querySelectorAll('td');
var highlight = function () {
// take this person's name from the 2nd cell
var name = this.parentNode.children[1].innerHTML;
// highlight cells with same name
tds.forEach(function (td) {
var tr = td.parentNode;
// compare other's person name with this person name
// highlight if there is a match
tr.classList.toggle('highlight', tr.children[1].innerHTML === name)
});
}
// attach an event listener to all cells
tds.forEach(function (td) {
td.onmouseover = highlight;
});
Demo

jQuery Each Loop Not updating HTML in variable

I have a variable html that stores HTML:
<tr class="odd">
<td class="charge1">0</td>
<td class="nc1">0</td>
</tr>
<tr class="even">
<td class="charge2">0</td>
<td class="nc2">0</td>
</tr>
<tr class="odd">
<td class="charge3">250</td>
<td class="nc3">0</td>
</tr>
Basically I need to add the values for the td with the class starting with charge to the values for the td with the class starting with nc and replace the value in the td with class starting with nc with the sum. The values in both td's in each row could change, so the code needs to be dynamic. So for this example, the resulting HMTL in the variable should be:
<tr class="odd">
<td class="charge1">0</td>
<td class="nc1">0</td>
</tr>
<tr class="even">
<td class="charge2">0</td>
<td class="nc2">0</td>
</tr>
<tr class="odd">
<td class="charge3">250</td>
<td class="nc3">250</td>
</tr>
In this example, the only row that actually changes is the third row. The td starting with class nc now shows 250 instead of the original 0.
I have to use the variable html later in the code with the updated td information if it did change.
This is the code that I have, but it's not working:
var html = $('#chargetable').html();
console.log(html);
$('[class*=nc]', html).each(function(){
var ncamount = $(this).html();
var chargeamount = $(this).parents('tr').find('[class*=charge]').html();
var totalnc = parseFloat(chargeamount) + parseFloat(ncamount);
$(this).html(totalnc);
console.log(chargeamount + ' ' + ncamount + ' ' + totalnc);
});
console.log(html);
This is the results of the console's log:
<tr class="odd">
<td class="charge1">0</td>
<td class="nc1">0</td>
</tr>
<tr class="even">
<td class="charge2">0</td>
<td class="nc2">0</td>
</tr>
<tr class="odd">
<td class="charge3">250</td>
<td class="nc3">0</td>
</tr>
0 0 0
0 0 0
250 0 250
<tr class="odd">
<td class="charge1">0</td>
<td class="nc1">0</td>
</tr>
<tr class="even">
<td class="charge2">0</td>
<td class="nc2">0</td>
</tr>
<tr class="odd">
<td class="charge3">250</td>
<td class="nc3">0</td>
</tr>
The html variable isn't being updated, but I can't for the life of me figure out how to get it to update, short of splitting the variable, replacing the td with class nc, and recreating the html variable on each iteration. I'm thinking there's got to be a better way to do this.
Any help is very much appreciated.
The problem with you code is that you cannot use html variable in this line
$('[class*=nc]', html)
the second parameter is used to define scope in which jQuery searches for the selector.
So, like document,parent.document(if its iframe etc..)
If you need the original dom you can use jQuery .clone() to store the original dom like this
//if you require the original code for later clone it
var htmlclone = $('#chargetable').clone().html();
console.log(htmlclone);
$('#chargetable [class*=nc]').each(function(){
var ncamount = $(this).html();
var chargeamount = $(this).parents('tr').find('[class*=charge]').html();
var totalnc = parseFloat(chargeamount) + parseFloat(ncamount);
$(this).html(totalnc);
console.log(chargeamount + ' ' + ncamount + ' ' + totalnc);
});
console.log(htmlclone);
Here is a fiddle http://jsfiddle.net/z4n7kjcf/
$(function () {
var $chargeTable = $("#chargetable");
var $chargeTableCloned = $chargeTable.clone();
var $chargeTableRows = $("tr", $chargeTableCloned);
$.each($chargeTableRows, function(i, $tr){
var $tdCharge = $("td[class^='charge']", $tr);
var $tdNc = $("td[class^='nc']", $tr);
var charge = parseInt($tdCharge.text(), 10);
var nc = parseInt($tdNc.text(), 10);
$tdNc.text(charge + nc);
});
$chargeTable.after($chargeTableCloned);
});
Example

change td properties and keep value from extracted data from site

I have this structure to get data from another webstie
$searchURL = "http://www.anotherwebsite.com";
$html = file_get_contents($searchURL);
$patternform = '/(<tbody.*<\/tbody>)/sm';
preg_match_all($patternform ,$html,$matches);
preg
echo $matches[0][0];
<tr class="even hidden">
<td colspan="3">OB I</td>
<td colspan="5">vízilabda, ffi</td>
</tr>
<tr class="odd">
<td class="opener nowrap"><ins></ins>063</td>
<td class="center nowrap"><ins class="sport jegkorong" title="jégkorong"><span>jégkorong</span></ins>3</td>
<td><strong>Magyarország - Lengyelország</strong></td>
<td class="center">
1.59 </td>
<td class="center">
4.20 </td>
<td class="center">
3.55 </td>
<td class="nowrap">
P 18:15 </td>
<td class="nowrap">
nov. 08 </td>
</tr>
^^
I had this "input"
Question is:
How can I change three td value to javascript onclick event (extra: that I want to store the name of the event and I want to store the selected odds and add to new div or table line by line.)
I think preg_replace need but regexp. not my desk.
Why must javascript be used? Would simply using the HTML onclick work?
<td onclick="SomethingFunky">

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