This script stops working the moment I add a table inside a table, so how to get it worked?
I don't need any jQuery solutions, I want pure JavaScript. Here's my script found on the Internet:
<script>
function show_hide_column(col_no, do_show) {
var stl;
if (do_show) stl = 'block'
else stl = 'none';
var tbl = document.getElementById('id_of_table');
var rows = tbl.getElementsByTagName('tr');
for (var row=1; row<rows.length;row++) {
var cels = rows[row].getElementsByTagName('td')
cels[col_no].style.display=stl;
}
}
</script>
Here's my HTML:
<table id='id_of_table' border=1>
<tr><td colspan="4"><table><tr><td></td></tr></table></td></tr>
<tr><td> 2</td><td> two</td><td> deux</td><td> zwei</td></tr>
<tr><td> 3</td><td> three</td><td> trois</td><td> drei</td></tr>
<tr><td> 4</td><td> four</td><td>quattre</td><td> vier</td></tr>
<tr><td> 5</td><td> five</td><td> cinq</td><td>fünf</td></tr>
<tr><td> 6</td><td> six</td><td> six</td><td> sechs</td></tr>
</table>
And here's my Form:
<form>
Enter column no: <input type='text' name=col_no><br>
<input type='button' onClick='javascript:show_hide_column(col_no.value, true);' value='show'>
<input type='button' onClick='javascript:show_hide_column(col_no.value, false);' value='hide'>
</form>
You can leverage the col tag and then the solution is straightforward using only vanilla JavaScript. The col tag has only a few CSS attributes, but visibility is one of them:
function show_hide_column( col_no, do_show ){
const table = document.getElementById( 'id_of_table' )
const column = table.getElementsByTagName( 'col' )[col_no]
if ( column ){
column.style.visibility = do_show?"":"collapse";
}
}
const btnHide = document.getElementById( 'btnHide' )
btnHide.addEventListener( "click", () => show_hide_column( 2, false ))
const btnShow = document.getElementById( 'btnShow' )
btnShow.addEventListener( "click", () => show_hide_column( 2, true ))
<table id='id_of_table' border=1>
<col class="col1"/>
<col class="col2"/>
<col class="col3"/>
<col class="col4"/>
<tr><td colspan="4"><table><tr><td></td></tr></table></td></tr>
<tr><td> 2</td><td> two</td><td> deux</td><td> zwei</td></tr>
<tr><td> 3</td><td> three</td><td> trois</td><td> drei</td></tr>
<tr><td> 4</td><td> four</td><td>quattre</td><td> vier</td></tr>
<tr><td> 5</td><td> five</td><td> cinq</td><td>fÜnf</td></tr>
<tr><td> 6</td><td> six</td><td> six</td><td> sechs</td></tr>
</table>
<button id="btnHide">hide French</button>
<button id="btnShow">show French</button>
References:
col
visibility on quirksmode
You could use children and check their tagName to make sure they're td's. Something like this:
function show_hide_column(col_no, do_show) {
var tbl = document.getElementById('id_of_table');
var rows = tbl.getElementsByTagName('tr');
for (var row = 0; row < rows.length; row++) {
var cols = rows[row].children;
if (col_no >= 0 && col_no < cols.length) {
var cell = cols[col_no];
if (cell.tagName == 'TD') cell.style.display = do_show ? 'block' : 'none';
}
}
}
Edit: Here's a working example: http://jsfiddle.net/3DjhL/2/.
Edit:
In fact, I've just remembered the rows and cols properties, which make it even simpler. See http://jsfiddle.net/3DjhL/4/ to see it in action.
function show_hide_column(col_no, do_show) {
var rows = document.getElementById('id_of_table').rows;
for (var row = 0; row < rows.length; row++) {
var cols = rows[row].cells;
if (col_no >= 0 && col_no < cols.length) {
cols[col_no].style.display = do_show ? '' : 'none';
}
}
}
Oh, and if you think the column numbers should start at 1 (which they don't), you'll have to offset that somewhere. For example at the top of show_hide_column():
col_no = col_no - 1;
The important thing here is the selector, it could be vanilla or jquery:
document.querySelectorAll('#yourtable tbody tr td:nth-child(1)').forEach(el=>el.style.display = 'none')
From the code above, the nth-child(1) selector has a 1-based index, there you define the column you want to hide ;)
I had a situation where it would have been a very big hassle to modify every single TD value and add the appropriate class name so I could toggle it. As a result I wrote some JavaScript to do that automatically. Please see the following code.
tbl = document.getElementById("Mytable")
classes = getClasses(tbl.rows[0]);
setClasses(tbl, classes);
toggleCol("col0");
toggleCol("col1");
function getClasses(row){
var cn = 0;
var classes = new Array();
for(x=0; x < row.cells.length; x++){
var cell = row.cells[x];
var c = new Column(cell.textContent.trim(), cell.offsetLeft, cell.offsetLeft + cell.offsetWidth, x);
classes[x]= c;
}
return classes;
}
function Column(name, left, right, cols) {
this.name = name;
this.left = left;
this.right = right;
this.cols = cols;
}
function setClasses(table, classes){
var rowSpans = new Array();
for(x=0; x < table.rows.length; x++){
var row = table.rows[x];
for(y=0; y < row.cells.length; y++){
var cell = row.cells[y];
for(z=0; z < classes.length; z++){
if(cell.offsetLeft >= classes[z].left && cell.offsetLeft <= classes[z].right){
cell.className = "col" + classes[z].cols;
}
}
}
}
}
function toggleCol(name){
var cols = document.getElementsByClassName(name);
for(x=0; x < cols.length; x++){
cols[x].style.display= (cols[x].style.display == 'none') ? '' : 'none';
}
}
In my example I take a look at the first row to set the top level header (In my example I had several who had colspans). It uses the offsetLeft and offsetWidth to determine the range of the top header (which in my cases has sub headers), so that all sub-columns would toggle with its parent.
Based on these values setClasses sets the appropriate classes to all the elements.
In my example I then toggle "col0" and "col1", so they would be invisible (Running the function again would make them visible again).
Related
So i have a script like this to make a 2x2 table by javascript
function createtable(){
var tbl = document.getElementById('x');
if (tbl.contains()==false){
tbl.setAttribute('border', '1');
var tbdy = document.createElement('tbody');
for (var i = 0; i < 2; i++) {
var tr = document.createElement('tr');
for (var j = 0; j < 2; j++) {
var td = document.createElement('td');
tr.appendChild(td);
td.style.height='50px';
td.style.width='50px';
}
tbdy.appendChild(tr);
}
tbl.appendChild(tbdy);
}
<form>
<input type="button" value="Create Table" onclick="createtable()"> <br>
</form>
<table id="x"> </table>
I want to check if table x contains anything or not to create itself. Im trying to use the contains() to check but it doesnt work.
You can check the number of rows in the table:
var x = document.getElementById("myTable").rows.length;
See reference here: https://www.w3schools.com/jsref/coll_table_rows.asp
Using this:
var tbl = document.getElementById('x');
if (tbl.rows.length == 0) {
// empty
}
If you want to check if there are any inside table do this
document.getElementById("myTable").rows.length
More info here
you can Check the Row Counts
var tbl = document.getElementById('x');
if(tbl.rows.length==0){
}
if the tbl.rows.length is 0 that means the table don't have any rows
There are multiple ways. One of way, you can use childElementCount property.
if (tbl.childElementCount==0)
{
}
For more details you can refere link
In this case, since there are no child elements or text nodes in your table, you can just check to see if the innerHTML property is falsy. This prevents your createtable function from appending additional children after the function has been run once. For example:
function createtable() {
var tbl = document.getElementById('x');
if (!tbl.innerHTML) {
var tbdy = document.createElement('tbody');
tbl.setAttribute('border', '1');
for (var i = 0; i < 2; i++) {
var tr = document.createElement('tr');
for (var j = 0; j < 2; j++) {
var td = document.createElement('td');
tr.appendChild(td);
td.style.height = '50px';
td.style.width = '50px';
}
tbdy.appendChild(tr);
}
tbl.appendChild(tbdy);
}
}
<form>
<input type="button" value="Create Table" onclick="createtable()">
<br>
</form>
<table id="x"></table>
Plain javascript:
!![].length
or use Lodash
_.head([]);
// => undefined
I trying to get the <th> content of the clicked <td> item.
here is the fiddle: http://jsfiddle.net/zrccq447/
the thing is, the <th> can have colspan 2 or 3, this is the point where I am stuck. this is my code
$('#table9').on('click', 'td:not(:nth-child(1))', function () {
var td = $(this);
var clicked_pos = td.index();
var x = $('#headerx9 th:nth-child(' + (clicked_pos) + ')').text();
var xy = td.text();
alert(x);
});
i want x to be the <th> of clicked td. the problem is now that if you click on some td that shares the th with other tds, i am getting the wrong th.
appreciate any help
I've updated your JsFiddle with the answer found here: Finding a colSpan Header for one of the cells or td's is Spans
JsFiddle: http://jsfiddle.net/zrccq447/4/
$('#table9').on('click', 'td:not(:nth-child(1))', function () {
var td = $(this);
var clicked_pos = td.index();
var x = $('#headerx9 th:nth-child(' + thLocator[clicked_pos] + ')').text();
var xy = td.text();
alert(x);
});
var thLocator = [], colCount = 1;
$('#table9').find('tr:first th').each(function () {
for (var i = 0; i < this.colSpan; i++) {
thLocator.push(colCount);
}
colCount++;
});
Following on from my comment you need to sum up the colspans (or default 1) for each TH until you get enough to match the column you desire:
http://jsfiddle.net/TrueBlueAussie/zrccq447/5/
$('#table9').on('click', 'td:not(:nth-child(1))', function () {
var td = $(this);
var clicked_pos = td.index();
var cols = 0;
var $table = td.closest('table');
var $ths = $table.find('tr th');
for (var i = 1; i < $ths.length; i++) {
var $th = $ths.eq(i);
cols += ~~$th.attr('colspan') || 1;
if (cols >= clicked_pos) {
var x = $th.text();
alert(x);
break;
}
}
});
I tried to keep it generic, so it finds the appropriate table and headers on the fly.
One approach is to get store a reference to each TH, in order, in an array and call the text from the array based on the location of the td.
var thholder = $('table th'),
th = [];
for(var i = 0; i < thholder.length; i++) {
var thi = $(thholder[i]);
for(var j = 0; j < (thi.attr('colspan') || 1); j++) {
th.push(thi);
}
}
$('#table9').on('click', 'td:not(:nth-child(1))', function () {
var td = $(this);
var clicked_pos = td.index();
alert(th[clicked_pos].text());
});
http://jsfiddle.net/zrccq447/3/
This code is not optimised, but shows the approach:
Loop through all the TH in the table.
If the TH does not have the attribute 'colspan', then set the attribute to a value of 1.
Create a loop for each value of colspan and save a reference to the current TH in the array.
When you click on a TD, get it's clicked position and retrieve the text of the TH at that position in the array and alert it :)
I have a table with n number of rows. The value of n changes/updates every minute.
The first <td> of every row will either contain some text, or it will be blank.
I want to delete/remove all the rows except, the first row and the row whose first cell contains the text 'xyz'.
So, how will I be able to do this?
This table element is stored in the variable parentTable.
I'm kind of new to javascript and programming. Any help would be appreciated. Thanks.
I tested it with just the second row, but nothing happened even though the text is not xyz in the cell.
if(parentNode.childNodes[1].innerText !== "xyz")
parentTable.deleteRow[1];
And how do I loop around every row and do this?
EDIT: HTML for first cell in every row.
<td class=wbwhite align=center width=40 style="border-top: none; border-left:none; border-right:none;">
<a href="www.kasdjfkasd.sadsdk.comi" class=pi>xyz</a>
</td>
Try this:
var table = parentTable;
var rowCount = table.rows.length;
for ( var i = 1; i < rowCount; i++ )
{
var row = table.rows[i];
var val= row.cells[0].childNodes[0].innerHTML.toString();
if ( 'xyz' != val )
{
table.deleteRow( i );
rowCount--;
i--;
}
}
Use this code (pure JavaScript):
(assuming table has id = tableId).
var all = document.querySelectorAll('#tableId > tbody > tr');
// i = 1 not i = 0 to keep the first row.
for (var i = 1; i < all.length; i++) {
var td = all[i].querySelectorAll('td')[0];
if ( td.textContent != "xyz" ) {
all[i].parentNode.removeChild(all[i]);
}
}
You can try this
var allRows = parentTable.getElementsByTagName('TR');
for(var i=1; i<allRows.length;)
{
var tr = allRows[i];
var firstTd = tr.getElementsByTagName('TD')[0];
if(firstTd.innerHTML !== 'xyz')
{
tr.parentNode.removeChild(tr);
}else{
i++;
}
}
I am trying to create a table that is generated by user input data.
The table is reflecting a grid therfore I want the id of each cell to be the co ordinate of that grid. So the id of the bottom left cell would be id00. The top right cell id would be the maximum size of the grid that the user has entered.
So for example if data entered; x value=3; y value=3
this would produce the following table:
<table>
<tr><td id="id03"></td><td id="id13"></td><td id="id23"></td><td id="id33"></td></tr>
<tr><td id="id02"></td><td id="id12"></td><td id="id22"></td><td id="id32"></td></tr>
<tr><td id="id01"></td><td id="id11"></td><td id="id21"></td><td id="id31"></td></tr>
<tr><td id="id00"></td><td id="id10"></td><td id="id20"></td><td id="id30"></td></tr>
</table>
I have identified the basic concept for the code as you can see below:
<table>
Create a loop, initial value of r= 0; maximum value of r=y
r =0 <tr> create a secondary loop, initial value of n=0; maximum value of n = x; r remains constant for row
n=0; r= 0 <td id = “id” + “[x- (x-n)]” + “[y-r]” > </td>
….
n=3; r= 0* <td id = “id” + “[x- (x-n)]” + “[y-r]” > </td>
</tr>
….
r =3 <tr> n=0; r= 3 <td id = “id” + “[x- (x-n)]” + “[y-r]” > </td>
….
n=3; r= 3<td id = “id” + “[x- (x-n)]” + “[y-r]” > </td>
</tr>
</table>
I want to develop it in Javascript but I am new to the language and I am having trouble coding it.
Any help anyone could provide would be greatly appreciated.
Try this :
var x = 3; // value from input
var y = 4; // value from input
var table = document.getElementById("myTable");
for(var i = 0; i < y; i++) {
var row = table.insertRow(-1);
for(var j = 0; j < x; j++) {
var cell = row.insertCell(-1);
cell.id = "id" + (j) + (y - i - 1);
cell.innerHTML = cell.id;
}
}
Working example
Try something like this :
var rows = parseInt(document.getElementById('rows').value,10); // get input value
var cols = parseInt(document.getElementById('cols').value,10); // get input value
var table = document.createElement('table'); // create table element
table.border = "1"; // set some attributes
var prevrow; // used to store previous row element
for (var r = 0; r < (rows+1); r++) { // loop rows
var row = document.createElement('tr'); // create tr
for (var c = 0; c < (cols+1); c++) { // loop cols
var col = document.createElement('td'); // create td
col.id = 'id' + r + c; // set id of tr
col.innerHTML = col.id; // add some text
row.appendChild(col); // append td to tr
}
// if first tr then create append to table else insert before previous tr
if (prevrow) {
table.insertBefore(row, prevrow);
} else {
table.appendChild(row);
}
// store newly create tr
prevrow = row;
}
// append the new table to the output div
document.getElementById('output').appendChild(table);
Uses document.createElement(), element.appendChild() and element.insertBefore() to build the table
Working example here
In this example:
<table border="1">
<col id="col0" style="background-color: #FFFF00"/>
<col id="col1" style="background-color: #FF0000"/>
<tr><td rowspan="2">1</td><td>2</td><td>3</td></tr>
<tr><td>4</td><td>5</td><td>6</td></tr>
<tr><td>7</td><td>8</td><td>9</td></tr>
</table>
How can I get the col’s id of td 4?
If I get it's column number with this jquery command:
var cn = $(this).parent().children().index($(this));
cn will be 0, but it’s style shows that it belongs to col1
and I need a commend like td.col.id
when I set rowspan="2" at the td above a td (eg. td 4) this td's column number will be different from it's order of col(or colgroup) and I set background color to show it.
Edit:
I believe there is a way to solve this problem, because when td knows about it's col(colgroup) there must be a way to ask it from td at dom tree. (Td4 you show style of a specific col, who is that col?)
<td>4</td> is the first child of the second tablerow, so you should indeed get column 0.
instead of elaborating a complex function that detects rowspans etc, it might be advisable to just assign ids to each table cell, or create another custom solution for your table.
e.g. you know in advance how many columns each specific row has? Or you use the actual background color or a 'secret' css attribute as identification.
ps. my useless fiddle until I understood the actual problem.
edit (read discussion below):
as described here, you are not supposed to create custom css attributes; these are often ignored by the browser (and not available via .attr()).
Sahar's solution was to mark each element affected by a merging of rows to remember for how many columns the element should count.
You first have to calculate the column number of the td itself.
This is done by counting the number of tds before our td; taking colspan attributes into account:
function getElementColumn(td)
{
var tr = td.parentNode;
var col = 0;
for (var i = 0, l = tr.childNodes.length; i < l; ++i) {
var td2 = tr.childNodes[i];
if (td2.nodeType != 1) continue;
if (td2.nodeName.toLowerCase() != 'td' && td2.nodeName.toLowerCase() != 'th') continue;
if (td2 === td) {
return col;
}
var colspan = +td2.getAttribute('colspan') || 1;
col += colspan;
}
}
Then you can iterate the col elements and return the one matching the column number.
We first have to find the colgroup element. Then it's similar to computing the column number of the td:
function getCol(table, colNumber)
{
var col = 0;
var cg;
for (var i = 0, l = table.childNodes.length; i < l; ++i) {
var elem = table.childNodes[i];
if (elem.nodeType != 1) continue;
if (elem.nodeName.toLowerCase() != 'colgroup') continue;
cg = elem;
break;
}
if (!cg) return;
for (var i = 0, l = cg.childNodes.length; i < l; ++i) {
var elem = cg.childNodes[i];
console.log(elem);
if (elem.nodeType != 1) continue;
if (elem.nodeName.toLowerCase() != 'col') continue;
if (col == colNumber) return elem;
var colspan = +elem.getAttribute('span') || 1;
col += colspan;
}
}
With these two function you should be able to do this:
var id = getCol(table, getElementColumn(td)).id;
http://jsfiddle.net/wHyUQ/1/
jQuery version
function getElementColumn(td)
{
var col = 0;
$(td).prevAll('td, th').each(function() {
col += +$(this).attr('colspan') || 1;
});
return col;
}
function getCol(table, colNumber)
{
var col = 0, elem;
$(table).find('> colgroup > col').each(function() {
if (colNumber == col) {
elem = this;
return false;
}
col += +$(this).attr('span') || 1;
});
return elem;
}
http://jsfiddle.net/wHyUQ/2/
Resolving rowspans or colspans would be incredibly complex. I suggest you to iterate over all col-elements, set a width of 0px to them and check if this affected the width of your td or th element. If so, this is the related column.
Example:
// Your table elements
$table = $('yourTableSelector');
$cell = $('td or th');
$cols = $table.find('colgroup > col');
// determine the related col
// by setting a width of 0px. the
// resulting width on the element should be negative or zero.
// this is hacky, but the other way would
// be to resolve rowspans and colspans, which
// would be incredibly complex.
var $relatedColumn = $();
$cols.each(function(){
var $col = $(this);
var prevStyle = $col.attr('style') === 'string' ? $col.attr('style'): '';
$col.css('width', '0px');
if($cell.width() <= 0){
$relatedColumn = $col;
$col.attr('style', prevStyle); // reset
return false;
} else {
$col.attr('style', prevStyle); // reset
}
});