I am trying to grab the contents from one column only. but it's grabbing that one column as well as the rest of the row content and displaying it. How can I just grab only the age column?
document.getElementById('info').innerHTML = "";
var myTab = document.getElementById('empTable');
// LOOP THROUGH EACH ROW OF THE TABLE AFTER HEADER.
for (i = 1; i < myTab.rows.length; i++) {
// GET THE CELLS COLLECTION OF THE CURRENT ROW.
var objCells = myTab.rows.item(i).cells;
// LOOP THROUGH EACH CELL OF THE CURENT ROW TO READ CELL VALUES.
for (var j = 2; j < objCells.length; j++) {
info.innerHTML = info.innerHTML + ' ' + objCells.item(j).innerHTML;
}
info.innerHTML = info.innerHTML + ',';
}
th,
td,
p,
input {
font: 14px Verdana;
}
table,
th,
td {
border: solid 1px #DDD;
border-collapse: collapse;
padding: 2px 3px;
text-align: center;
}
th {
font-weight: bold;
}
<head>
<title>Read Data from HTML Table uisng JavaScript</title>
</head>
<body>
<table id="empTable">
<tr>
<th>ID</th>
<th>Employee Name</th>
<th>Age</th>
<th>Color</th>
</tr>
<tr>
<td>01</td>
<td>Alpha</td>
<td>37</td>
<td>Blue</td>
</tr>
<tr>
<td>02</td>
<td>Bravo</td>
<td>29</td>
<td>Red</td>
</tr>
</table>
<p id="info"></p>
Outcome:
37 Blue, 29 Red,
Desired outcome:
37, 29
Any help and explanation is greatly appreciated!
Thanks,
bfox
You're looping through all elements of objCells after index 2 which is returning objCells[2] (37) and objCells[3] (blue)
just access objCells[2] like so
for (var j = 2; j < objCells.length; j++) {
info.innerHTML = info.innerHTML + ' ' + objCells.item(j).innerHTML;
}
Should be
info.innerHTML = info.innerHTML + ' ' + objCells.item(2).innerHTML;
Instead of looping through all the cells of each row, you need to only process the 3rd cell of each row, here is an example:
var myTab = document.getElementById('empTable');
var ages = [];
for (i = 1; i < myTab.rows.length; i++) {
var currentRow = myTab.rows[i];
var ageCell = currentRow.cells[2];
ages.push(ageCell.textContent);
}
var info = document.getElementById('info');
info.innerHTML = ages.join();
th,
td,
p,
input {
font: 14px Verdana;
}
table,
th,
td {
border: solid 1px #DDD;
border-collapse: collapse;
padding: 2px 3px;
text-align: center;
}
th {
font-weight: bold;
}
<head>
<title>Read Data from HTML Table uisng JavaScript</title>
</head>
<body>
<table id="empTable">
<tr>
<th>ID</th>
<th>Employee Name</th>
<th>Age</th>
<th>Color</th>
</tr>
<tr>
<td>01</td>
<td>Alpha</td>
<td>37</td>
<td>Blue</td>
</tr>
<tr>
<td>02</td>
<td>Bravo</td>
<td>29</td>
<td>Red</td>
</tr>
</table>
<p id="info"></p>
What this does is to loop through each row and add the 3rd cell's text content to the ages array, once all the rows are processed, the #info element's inner HTML is set to a string representation of the ages array (.join() just creates a string which contains the string representation of each element of the array separated by a comma).
In the above code, the second for-loop is reading all cells starting from index-2.
This is causing all the unnecessary values to get concatenated.
The problem can be fixed by replacing the for-loop with an assignment statement in an if-condition.
Additionally, the trailing comma can be avoided by using an array instead of updating the inner-html of the result element inside the loop.
Here is the working code with the suggested change:
<!DOCTYPE html>
<html>
<head>
<title>Read Data from HTML Table uisng JavaScript</title>
</head>
<body>
<table id="empTable">
<tr>
<th>ID</th>
<th>Employee Name</th>
<th>Age</th>
<th>Color</th>
</tr>
<tr>
<td>01</td>
<td>Alpha</td>
<td>37</td>
<td>Blue</td>
</tr>
<tr>
<td>02</td>
<td>Bravo</td>
<td>29</td>
<td>Red</td>
</tr>
</table>
<p id="info"></p>
<script>
document.getElementById('info').innerHTML = "";
var myTab = document.getElementById('empTable');
// Declare a result array
var result = []
// LOOP THROUGH EACH ROW OF THE TABLE AFTER HEADER.
for (i = 1; i < myTab.rows.length; i++) {
// GET THE CELLS COLLECTION OF THE CURRENT ROW.
var objCells = myTab.rows.item(i).cells;
// Add the content of second cell to result array
if(objCells.length >= 2) {
result.push(objCells.item(2).innerHTML);
}
}
// Show the result array in the info element
document.getElementById('info').innerHTML = result
</script>
</body>
</html>
Output:
ID Employee Name Age Color
01 Alpha 37 Blue
02 Bravo 29 Red
37,29
Related
hi im working with datatable and its great but i have problem thats in complex header like this
<thead>
<tr><td>some text</td></tr>
<tr><td>some text</td></tr>
</thead>
now in showing page its like like this
when i hit print preview i gat result like this
that the first tr in thead is gone
i opened datatable.js file and i found this
var addRow = function ( d, tag ) {
var str = '<tr>';
for ( var i=0, ien=d.length ; i<ien ; i++ ) {
// null and undefined aren't useful in the print output
var dataOut = d[i] === null || d[i] === undefined ?
'' :
d[i];
var classAttr = columnClasses[i] ?
'class="'+columnClasses[i]+'"' :
'';
str += '<'+tag+' '+classAttr+'>'+dataOut+'</'+tag+'>';
}
return str + '</tr>';
};
// Construct a table for printing
var html = '<table class="'+dt.table().node().className+'">';
html += '<thead>';
// Adding logo to the page (repeats for every page while print)
if(config.repeatingHead.logo) {
var logoPosition = (['left','right','center'].indexOf(config.repeatingHead.logoPosition) > 0) ? config.repeatingHead.logoPosition : 'right';
html += '<tr><th colspan="'+data.header.length+'" style="padding: 0;margin: 0;text-align: '+logoPosition+';"><img style="'+config.repeatingHead.logoStyle+'" src="'+config.repeatingHead.logo+'"/></th></tr>';
}
// Adding title (repeats for every page while print)
if(config.repeatingHead.title) {
html += '<tr><th colspan="'+data.header.length+'">'+config.repeatingHead.title+'</th></tr>';
}
if ( config.header ) {
html += addRow( data.header, 'th' );
}
html += '</thead>';
html += '<tbody>';
for ( var i=0, ien=data.body.length ; i<ien ; i++ ) {
html += addRow( data.body[i], 'td' );
}
html += '</tbody>';
if ( config.footer && data.footer ) {
html += '<tfoot>'+ addRow( data.footer, 'th' ) +'</tfoot>';
}
html += '</table>';
and its just add the last tr in thead
but i couldn't put the first tr with print preview
thanks a lot
this is a jsfiddle ex
when you preview the table its showing with tow row at thead
but in print preview its showing only on tr in thead
enter link description here
As discussed in this topic from Datatables website, this feature is not yet available.
You asked for a work-around and since it is already mentioned not a feature for Datatables at the moment. You could simply convert it to a PDF through grabbing only the tables contents. Then add styling for the print window without any libraries. It really is just a window.
It is just a matter of injecting the right style before loading the window. So we just need to make sure we grab the style outputted by datatables and inject that.
CSS
table
{
width: 300px;
font-size: 17px;
}
table, th, td
{
border: solid 1px #DDD;
border-collapse: collapse;
padding: 2px 3px;
text-align: center;
} table
{
width: 300px;
font-size: 17px;
}
table, th, td
{
border: solid 1px #DDD;
border-collapse: collapse;
padding: 2px 3px;
text-align: center;
}
HTML
<div id="print-window">
<table id="example" class="display" style="width:100%">
<thead>
<tr>
<th rowspan="2">Name</th>
<th colspan="2">HR Information</th>
<th colspan="3">Contact</th>
</tr>
<tr>
<th>Position</th>
<th>Salary</th>
<th>Office</th>
<th>Extn.</th>
<th>E-mail</th>
</tr>
</thead>
<tbody>
<tr>
<td>Tiger Nixon</td>
<td>System Architect</td>
<td>$320,800</td>
<td>Edinburgh</td>
<td>5421</td>
<td>t.nixon#datatables.net</td>
</tr>
<tr>
<td>Garrett Winters</td>
<td>Accountant</td>
<td>$170,750</td>
<td>Tokyo</td>
<td>8422</td>
<td>g.winters#datatables.net</td>
</tr>
<tr>
<td>Ashton Cox</td>
<td>Junior Technical Author</td>
<td>$86,000</td>
<td>San Francisco</td>
<td>1562</td>
<td>a.cox#datatables.net</td>
</tr>
<tr>
<td>Cedric Kelly</td>
<td>Senior Javascript Developer</td>
<td>$433,060</td>
<td>Edinburgh</td>
<td>6224</td>
<td>c.kelly#datatables.net</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>Name</th>
<th>Position</th>
<th>Salary</th>
<th>Office</th>
<th>Extn.</th>
<th>E-mail</th>
</tr>
</tfoot>
</table>
</div>
<input type="button" value="Print" onclick="pdf()" />
Javascript
function pdf() {
let t = document.getElementById('print-window').innerHTML;
let style = "<style>";
style = style + "table {width: 100%; font-size: 17px;}";
style = style + "table, th, td {border: solid 1px #DDD; border-collapse: collapse;";
style = style + "padding: 2px 3px;text-align: center;}";
style = style + "</style>";
let win = window.open('', '', 'height=700,width=700');
win.document.write('<html><head>');
win.document.write('<title>Profile</title>');
win.document.write(style);
win.document.write('</head>');
win.document.write('<body>');
win.document.write(t);
win.document.write('</body></html>');
win.document.close();
win.print();
}
The td:nth-child('n') is not working over in my table it gives null in the log Where as it is working when i use children[n] it is a simple function for searching
I couldn't find the reason why it is giving out a null.. Here is the code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Table Searching</title>
<style>
th{
font-weight: bolder;
}
table, th, td{
font-size: 20px;
border: 2px solid black;
border-collapse: collapse;
}
</style>
</head>
<body>
<input type="text" name="search">
<button class="s" onclick="Search()">Search by Name</button>
<button class="s" onclick="Search()">Search by Country</button>
<button class="s" onclick="Search()">Search by Pet</button>
<table>
<tr>
<th>Name</th>
<th>Country</th>
<th>Pet</th>
</tr>
<tr>
<td>Abhi</td>
<td>Canada</td>
<td>koala</td>
</tr>
<tr>
<td>Riya</td>
<td>France</td>
<td>Parrot</td>
</tr>
<tr>
<td>Sid</td>
<td>UK</td>
<td>Pig</td>
</tr>
<tr>
<td>Kritika</td>
<td>Germany</td>
<td>Cat</td>
</tr>
<tr>
<td>Kartik</td>
<td>China</td>
<td>Frog</td>
</tr>
<tr>
<td>Radhika</td>
<td>India</td>
<td>Dog</td>
</tr>
</table>
<script>
var input=document.getElementsByName("search")[0];
var s=document.getElementsByClassName("s");
var n=0;
function Search(){
for (var j=0; j<s.length; j++)
{
console.log("element");
console.log(s[j]);
console.log("target");
console.log(event.target);
if(s[j]==event.target){
n=j;
console.log(n);
}
}
var val= input.value;
var a=document.querySelectorAll("table > tbody > tr");
console.log(a);
for(var i =0; i<a.length; i++)
{
var d = a[i].querySelector('td:nth-child("+n+")');
console.log(d);
if(d.innerHTML.toLowerCase()==val.toLowerCase()){
a[i].style.display="";
}
else
{
a[i].style.display="none";
}
}
}
</script>
</body>
</html>
Here are the three reasons why you are giving out null in your code:
First, as stated by Satpal, this code 'td:nth-child("+n+")' will not replace n by its value. It's like writing td:nth-child("+n+") in css.
The solution for this is to write: 'td:nth-child(' + n + ')'. You then concatenate the value of n with the rest of the string
The value of n is an index in a array, so it starts at 0 and ends at array.length - 1. The problem is that the nth-child selector actually selects the nth-child (brilliant naming), so if n is 0 (in the case of searching by name), you'll try to select the 0th-child, wihich doesn't exist... You then have to write: 'td:nth-child(' + (n + 1) + ')' or change the definition of n
You have no <tbody> tag in your HTML. Which means that all the content of the table will be wrapped in a tbody and your selector document.querySelectorAll("table > tbody > tr")will also selects the header of your table. To avoid that, change your HTML accordingly.
Something like that:
<table>
<thead>
<tr>
<th>Name</th>
<th>Country</th>
<th>Pet</th>
</tr>
</thead>
<tbody>
<tr>
<td>Abhi</td>
<td>Canada</td>
<td>koala</td>
</tr>
<tr>
<td>Riya</td>
<td>France</td>
<td>Parrot</td>
</tr>
<tr>
<td>Sid</td>
<td>UK</td>
<td>Pig</td>
</tr>
<tr>
<td>Kritika</td>
<td>Germany</td>
<td>Cat</td>
</tr>
<tr>
<td>Kartik</td>
<td>China</td>
<td>Frog</td>
</tr>
<tr>
<td>Radhika</td>
<td>India</td>
<td>Dog</td>
</tr>
</tbody>
</table>
Here is a jsfiddle where the search works fine: https://jsfiddle.net/n23685b6/1/
Hope this helps!
scrollToNthChild = (): * => {
var tableBody = document.getElementById('event-table-body');
var tableRows = tableBody.getElementsByTagName('tr');
let targetElement = tableRows[7];
targetElement.scrollIntoView();
}
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.
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");
}
}
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'})
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>
Sample table
<table>
<tr>
<td>Age</td>
<td>12</td>
<td>Gender</td>
<td>Male</td>
<td>Some long label</td>
<td>Some long label value</td>
...
...
could be more...
</tr>
</table>
Without the width:100% content should fit to each column container but I would like to make the table expand across the whole page. Setting table width: 100% equally distributes the column. I would like to make each label (Labels: Age, Gender, Some long label) fit it's column container and the rest equally divided among themselves (Values: 12, Male, Some long label value).
I know setting <td width="5%">Age</td> or setting it in css should do the job but I think this is counter productive especially if you have to do that with a lot of columns.
Is there a way to accomplish this in css with lesser code, javascript or jquery maybe? Any hint or direction on how this can be done?
Note:
I've read this but I would like to avoid injecting width="%" inside html.
May be colgroup can help you out. Try this
The HTML is:
<table border = "1" cellspacing = "0" cellpadding = "0">
<colgroup>
<col>
<col style="width:40%">
<col>
<col style="width:40%">
</colgroup>
<tr>
<td>Age</td>
<td>12</td>
<td>Gender</td>
<td>Male</td>
</tr>
</table>
If I understand you correctly, this is what you’re looking for:
table { width: 100% }
td:nth-child(odd) { width: 5% }
or if you want the content to be “hugged” by a cell:
table { width: 100% }
td:nth-child(odd) { width: 1%; white-space: nowrap }
$(function(){
$(window).load(function() {
updateCellWidth()
})
$(window).resize(function() {
updateCellWidth()
})
})
function updateCellWidth() {
var width = 0, cols = 0
$("table td:nth-child(even)").each(function(){
++cols
width += $(this).width()
})
if (cols > 0) {
var evenCellWidth=($("table").width()-width)/cols
$("table td:nth-child(even)").css("width", evenCellWidth + "px")
}
}
Are you looking for something like this.?
Then border-collapse, cellspacing & cellpadding might help you.
This is what I came up with. Thanks for the ideas.
<style type="text/css">
table {
border-collapse: collapse;
width: 100%;
}
table td {
border: 1px solid #000;
white-space: nowrap;
}
</style>
<body>
<table id="tbl1">
<tr>
<td>Age</td>
<td>12</td>
<td>Gender</td>
<td>Male</td>
<td>Some Long Label</td>
<td>Some Long Label Value</td>
</tr>
</table>
<script type="text/javascript">
var tbl = document.getElementById('tbl1');
var rowCount = tbl.rows.length;
var colCount = tbl.rows[0].cells.length;
for (var i = 0 ; i < colCount; i++) {
if (i%2 == 0) {
tbl.rows[0].cells[i].style.width = tbl.rows[0].cells[i].innerHTML.length + 'px';
}
}
</script>
I have the following HTML table:
<table border="1">
<tr>
<td>blue</td>
</tr>
<tr>
<td>red</td>
</tr>
<tr>
<td>black</td>
</tr>
</table>
I would like each row in this table have a number automatically assigned to each item.
How could he do?
The following CSS enumerates table rows (demo):
table {
counter-reset: rowNumber;
}
table tr::before {
display: table-cell;
counter-increment: rowNumber;
content: counter(rowNumber) ".";
padding-right: 0.3em;
text-align: right;
}
<table cellpadding="0">
<tr><td>blue</td></tr>
<tr><td>red</td></tr>
<tr><td>yellow</td></tr>
<tr><td>green</td></tr>
<tr><td>purple</td></tr>
<tr><td>orange</td></tr>
<tr><td>maroon</td></tr>
<tr><td>mauve</td></tr>
<tr><td>lavender</td></tr>
<tr><td>pink</td></tr>
<tr><td>brown</td></tr>
</table>
If the CSS cannot be used, try the following JavaScript code (demo):
var table = document.getElementsByTagName('table')[0],
rows = table.getElementsByTagName('tr'),
text = 'textContent' in document ? 'textContent' : 'innerText';
for (var i = 0, len = rows.length; i < len; i++) {
rows[i].children[0][text] = i + ': ' + rows[i].children[0][text];
}
<table border="1">
<tr>
<td>blue</td>
</tr>
<tr>
<td>red</td>
</tr>
<tr>
<td>black</td>
</tr>
</table>
And if you would use headers as well the following is the thing you need:
http://jsfiddle.net/davidThomas/7RyGX/
table {
counter-reset: rowNumber;
}
table tr:not(:first-child) {
counter-increment: rowNumber;
}
table tr td:first-child::before {
content: counter(rowNumber);
min-width: 1em;
margin-right: 0.5em;
}
note the: ":not(:first-child)" in there.
Here is a modification of David Thomas' CSS solution that works with or without a header row in the table. It increments the counter on the first td cell of each row (thereby skipping the row with only th cells):
table
{
counter-reset: rowNumber;
}
table tr > td:first-child
{
counter-increment: rowNumber;
}
table tr td:first-child::before
{
content: counter(rowNumber);
min-width: 1em;
margin-right: 0.5em;
}
You can see the behavior in this jsfiddle.
Here's a javascript solution that will add a cell at the beginning of each row , this cell will be used for numbering, if there is a th cell this gets a colspan=2 attribute.
var addNumeration = function(cl){
var table = document.querySelector('table.' + cl)
var trs = table.querySelectorAll('tr')
var counter = 1
Array.prototype.forEach.call(trs, function(x,i){
var firstChild = x.children[0]
if (firstChild.tagName === 'TD') {
var cell = document.createElement('td')
cell.textContent = counter ++
x.insertBefore(cell,firstChild)
} else {
firstChild.setAttribute('colspan',2)
}
})
}
addNumeration("test")
<table class="test" border="1">
<tr>
<th>hi!</th>
</tr>
<tr>
<td>blue</td>
</tr>
<tr>
<td>red</td>
</tr>
<tr>
<td>black</td>
</tr>
</table>