John Lombardi
John Lombardi

Reputation: 171

Adding class to specific cells of a html table

I am working on automating some reports for my company. We use R to summarize data in Excel, then use a combination of Rmarkdown, knitr, and the package "htmlTable" to create HTML.

I am currently using a CSS to modify some parts of the HTML code

markdownToHTML(paste0(basePath,'makeAppendixTableD1.md'),
             "appendixTableD1.html",
             stylesheet = paste0(basePath,"testStyleSheetUpdated.css")) 

where the HTML code output from above looks like:

<table class='gmisc_table' style='border-collapse: collapse; margin-top: 1em; margin-bottom: 1em;' >
<tbody>
<tr>
<td style='text-align: center;'>X1</td>
<td style='text-align: center;'>0</td>
</tr>
<tr>
<td style='text-align: center;'>X2</td>
<td style='text-align: center;'>0.35</td>
</tr>
<tr>
<td style='text-align: center;'>X3</td>
<td style='text-align: center;'>0.31</td>
</tr>
</tbody>
</table>

I can easily change the attributes like font-size or font-family using the CSS; however, I am a bit stumped for how to best edit specific columns or rows.

For example, I'd like to make X2 to be bold and italicized. But I won't always know where X2 is in the table. So I can't put in the CSS to modify the second row, first cell as for another table X2 may be the 10th row, first cell.

EDIT: Ideally, I'd like to be able to edit the whole <tr> </tr> for when X2 exists in the HTML.

Currently, I can use gsub() and some other string functions to find X2 in the HTML, then go back a couple characters to insert class = "X2". But this involves a fair bit of hardcoding.

Is there an easier way to do this using javaScript? I've looked into using the xtable package in R. There doesn't seem to be a way to add classes using the htmlTable package in R.

Upvotes: 1

Views: 15534

Answers (3)

Josh
Josh

Reputation: 4816

Pure JS:

Array.prototype.slice.call( document.getElementsByTagName("td"), 0 )
  .filter(function(x) {return x.innerHTML.match(/X2/)})
  .forEach(function(x) {
             x.classList.add('X2')                          // <td>
             x.parentNode.classList.add('OtherClassName')   // <tr>
  })

The last x is the DOM representation of the <td>, so you can navigate from there wherever you like, as the last line does with x.parentNode which is the <tr>...

jQuery on the first line only:

$.makeArray($("td"))
  .filter(function(x) {return x.innerHTML.match(/X2/)})
  .forEach(function(x) {x.classList.add('X2')})

ES6 with jQuery (won't work in IE11 due to no support for => yet):

$.makeArray($("td"))
  .filter(x => x.innerHTML.match(/X2/))
  .forEach(x => x.classList.add('X2'))

You would change line two to filter for an exact match if you so desired:

.filter(function(x) {return x.innerHTML === 'X2'})

Upvotes: 2

Tim
Tim

Reputation: 5691

var table = document.getElementsByTagName('table')[0];


var cols = table.getElementsByTagName('td');

for (var i = 0; i < cols.length; i++) {
  
  var col = cols[i];
  
  var content = col.innerText;
  
  // If it starts with 'X':
  if (content[0] === 'X') {
    col.className = content;
  }
}
.X1 { color: red; }
.X2 { color: blue; }
<table class='gmisc_table' style='border-collapse: collapse; margin-top: 1em; margin-bottom: 1em;' >
<tbody>
<tr>
<td style='text-align: center;'>X1</td>
<td style='text-align: center;'>0</td>
</tr>
<tr>
<td style='text-align: center;'>X2</td>
<td style='text-align: center;'>0.35</td>
</tr>
<tr>
<td style='text-align: center;'>X3</td>
<td style='text-align: center;'>0.31</td>
</tr>
</tbody>
</table>

Upvotes: 0

Seagrass
Seagrass

Reputation: 403

With vanilla JS, you could do something like:

//grab all td elements in your table
var tds = document.querySelectorAll(".gmisc_table td");
//iterate over each td
for (var i = 0; i < tds.length; i++) {
  var text = tds[i].innerText;
  //check for your target text
  if (text === "X2") {
    //add your class to the element containing this text
    tds[i].classList.add("X2");
  }
}

Upvotes: 7

Related Questions