How to find a table's column count using the DOM? - javascript

For row count using DOM, we have tablename.rows.length to get number of rows, but we don't have 'cols.length' for column count.
How can we find the number of columns (only using the DOM)?

I think you can use cells to calculate the column, assuming that the number of column of first row will be same for all
tablename.rows[0].cells.length;

I would use the table's rows property and the first row's cells property and total the colSpan property of each cell in the row. This will work in all major browsers back to IE 4 and should be pretty fast.
Demo: http://jsfiddle.net/Gtdru/
Code:
function getTableColumnCount(table) {
var columnCount = 0;
var rows = table.rows;
if (rows.length > 0) {
var cells = rows[0].cells;
for (var i = 0, len = cells.length; i < len; ++i) {
columnCount += cells[i].colSpan;
}
}
return columnCount;
}

There isn't such a concept in the DOM.
You could try and count the max number of td and th in tr :
var max = 0;
$('#tableId tr').each(function(){max=Math.max(max, $('td,th', this).length)});
Demonstration
If you want to take into account the colspan, it's a little heavier :
var max = 0;
$('#tableId tr').each(function(){
var inTr = 0;
$('td,th', this).each(function() { inTr += parseInt($(this).attr('colspan')) || 1;});
max = Math.max(max,inTr);
});
Demonstration

This will work with complex table headers :
$($('#table_id_here tbody tr')[0]).find('td').length

Here you go:
$(function() {
var colCount = 0;
$('tr:nth-child(1) td').each(function () {
if ($(this).prop('colspan')) {
colCount += +$(this).prop('colspan');
} else {
colCount++;
}
});
alert(colCount);
});​
jsfiddle

A very simple way to get the number of possible cols in any table is using the following (vanillaJS) function:
/**
* Calculates the number of columns based on any row using colSpan attribute.
*
* #param {HTMLElement} table : The table element to be count.
*
* #return {int} The number of columns this table has.
*/
var getTableColSpan = function getTableColSpan(table) {
var colSpan = 0; // initialize counter
var trs = table.querySelectorAll('tr'); // get firt tr cells.
for (var j = 0; j < trs.length; j++) {
var tr = trs[j];
var tds = tr.cells;
var trColSpan = 0; // initialize counter
// loops between columns and gets each one's colSpan
for (var i = 0; i < tds.length; ++i) {
trColSpan += tds[i].colSpan;
}
colSpan = trColSpan > colSpan ? trColSpan : colSpan;
}
return colSpan;
};

Related

How to hide columns with less than one input in Google sheets script?

I have a very large data set with clients and prices but not all clients get charged every price. When I filter out a client, I need to be able to run a macro to hide all of the columns that do not have a price associated with the header. I had the macro in Excel working fine but cannot transfer it into google sheets.
Excel VBA that worked perfectly:
Sub KolumnHider()
Dim wf As WorksheetFunction
Dim i As Long, r As Range
Set wf = Application.WorksheetFunction
For i = 1 To 1000
Set r = Cells(1, i).EntireColumn
If wf.Subtotal(3, r) < 2 Then r.Hidden = True
Next i
End Sub
This formula below is almost what I need. My issue is that I need it to hide the columns based on what is showing. When I filter out the data, I then want to run the macro and hide the columns with empty cells. It works when I filter to the certain row that 'ss.GetRange(3,1,1)' implies. For this example, If I filter to row 3 it works, but I have to change the code to say 6,1,1 for it to hide the correct info on row 6. I need it to hide only the row showing. Please help!
function hideEmptyHeaders() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var headers = ss.getRange(3, 1, 1, ss.getMaxColumns()).getValues()[0];
var columnIndex = 0, numColumns = 0;
headers.forEach(function(header, index) {
if (!header) {
if (!columnIndex)
columnIndex = index + 1;
numColumns++;
} else if (columnIndex > 0) {
ss.hideColumns(columnIndex, numColumns);
columnIndex = numColumns = 0;
}
});
if (columnIndex > 0) ss.hideColumns(columnIndex, numColumns);
}
Try this:
function hideBlankColumns() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var rg=sh.getDataRange();
var width=rg.getWidth();//could also be sh.getMaxColumns()
for(var c=1;c<=width;c++) {
if(getColHeight(c,sh,ss)==0) {
sh.hideColumns(c);
}
}
}
function getColHeight(col,sh,ss){
var ss=ss || SpreadsheetApp.getActive();
var sh=sh || ss.getActiveSheet();
var col=col || sh.getActiveCell().getColumn();
var rg=sh.getRange(1,col,sh.getLastRow(),1);
var vA=rg.getValues();
if(vA) {
while(vA.length && vA[vA.length-1][0].length==0){
vA.splice(vA.length-1,1);
}
return vA.length;
}
return 0;
}
Try this,
function myFunction() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getActiveSheet();
var i;
var j;
for(i=1;i<=1000;i++)
{
var count = 0;
var r = sheet.getLastRow();
for(j=1;j<r;j++)
{
if(!sheet.getRange(j,i).isBlank())
{
count++;
}
}
if(count < 2)
{
sheet.hideColumns(i);
}
}
}
Problem
You have rows hidden by a filter
You want to hide all columns, which do not have contents in the non-hidden cells
Solution
You need a function that returns you the hidden rows
You loop through all columns
For each column you loop through all rows and check if the row is not hidden
For all non-hidden rows, you check if the cell in given column has contents
If non of the non-hidden cells in a column has contents, you hide this column
If I understood right that this is what you want to do - here is a script that allows you to do so.
function getIndexesOfFilteredRows(ssId, sheetId) {
var hiddenRows = [];
// get row metadata to find the hidden rows
var fields = "sheets(data(rowMetadata(hiddenByFilter)),properties/sheetId)";
var sheets = Sheets.Spreadsheets.get(ssId, {fields: fields}).sheets;
//Find the right sheet
for (var i = 0; i < sheets.length; i++) {
if (sheets[i].properties.sheetId == sheetId) {
var data = sheets[i].data;
var rows = data[0].rowMetadata;
for (var j = 0; j < rows.length; j++) {
//push the indexes of all hodden rows into an array
if (rows[j].hiddenByFilter) hiddenRows.push(j);
}
}
}
//return indexes of hidden rows
return hiddenRows;
}
function hideEmptyHeaders() {
var ssId='XXXXX';
var sheetId=0;// adjust if necessary
//get the rows that are hidden by a filter
var hidden=getIndexesOfFilteredRows(ssId, sheetId);
var sheet=SpreadsheetApp.openById(ssId).getSheets()[sheetId];
//get all sheet contents
var rangeValues=sheet.getDataRange().getValues();
//check for every column either the not hidden part of the column is empty
for(var j=0;j<rangeValues[0].length;j++) {
// loop through all data rows
for(var i=0;i<rangeValues.length;i++) {
//check if the row is not hidden
if((hidden.indexOf(i)+1)==false) {
// if the row is not hidden, check if the cell in column j has content
if(rangeValues[i][j]!=""||rangeValues[i][j]!="") {
//if the cell has content, jump to the next column, otherwise check first all the other rows
break;
}
}
// if no content has been found in column j after ite5rating through all non-hidden rows, hide column j
if(i==(rangeValues.length-1)) {
sheet.hideColumns(j+1)
}
}
}
}

Name each cell on each row from 1 to 9

the problemI want to make a sudoku solver and to do that I need to name each cell from 1 to 9 in every row. If you know another way to make this please tell me. Here's the code:
function crear (){
var table = document.getElementById("table");
// enter code here
for (var i = 1; i < 10; i++) {
var showfila = document.createElement("TR");
showfila.setAttribute("id", "myTr" + i);
document.getElementById("table").appendChild(showfila);
for (var a = 1; a < 10; a++) {
var input = document.createElement("INPUT");
input.setAttribute("id", "myInp" + a);
document.getElementById("myTr" + i).appendChild(input);
document.getElementById("myInp" + a).value=a;
}
}
}
I'm assuming the "name" you are talking about for each cell is the name property and also that these cells need to be created (based on your code) so you can do something like this:
EDIT
The name now includes the corresponding row and column. I also added comments so that if this is not what you are looking for, you can refer to them to edit your code correctly.
function createTable(){
var table = document.getElementById("table");
//Loop for rows
for (var i = 1; i < 10; i++) {
//Loop for columns
for (var j = 1; j < 10; j++) {
var cell = document.createElement("TR");
//var i would be the row and var j would be the column
cell.name=i+"-"+j;
table.appendChild(cell);
}
}
}

Create a title for each column on a table using a loop. JavaScript

I want the title for each column on a table to be'A','B','C' etc, I want to be able to change how many columns there are so I want to use a loop.
Code so far:
JavaScript:
<script>
document.getElementById('dtable').innerHTML = '';
var table = document.getElementById("dtable")
Rows = 4
for (var count = 0; count <= Rows; count++) {
var header = table.createTHead(0);
var row = header.insertRow(0);
var character = String.fromCharCode(65 + count);
var cell = row.insertCell(count);
cell.innerHTML =('<b>'+character+'</b>');
}
</script>
HTML:
<div id='div1'><table id="dtable"></table></div>
You were creating one row in the header for each column.
Moving the thead creation outside the loop fixed it.
document.getElementById('dtable').innerHTML = '';
var table = document.getElementById("dtable");
var header = table.createTHead(0);
var row = header.insertRow(0);
Rows = 4
for (var count = 0; count <= Rows; count++) {
var character = String.fromCharCode(65 + count);
var cell = row.insertCell(count);
cell.innerHTML =('<b>'+character+'</b>');
}
<div id='div1'><table id="dtable"></table></div>
You don't want to create a new row inside of the loop right? Move the head and row creation outside of the loop.
like:
<script>
document.getElementById('dtable').innerHTML = '';
var table = document.getElementById("dtable")
Rows = 4
var header = table.createTHead(0);
var row = header.insertRow(0);
for (var count = 0; count <= Rows; count++) {
var character = String.fromCharCode(65 + count);
var cell = row.insertCell(count);
cell.innerHTML =('<b>'+character+'</b>');
}
</script>
If you want it to look like a table with borders and such you'll have to add css styling but that should print a b c d e
Your problem is that you are creating the header and the row inside your for loop, which means that you will be creating a new row each time, which causes problems with row.insertCell. The first iteration works because you are inserting a cell in the 0th position, but the second iteration of the loop attempts to insert a cell in the 1st position, when a 0th position cell does not exist, hence why it throws an error. Try this and it should work for you:
document.getElementById('dtable').innerHTML = '';
var table = document.getElementById("dtable");
var Rows = 4;
var header = table.createTHead(0);
var row = header.insertRow(0);
for (var count = 0; count <= Rows; count++) {
var character = String.fromCharCode(65 + count);
var cell = row.insertCell(count);
cell.innerHTML =('<b>'+character+'</b>');
}
<div id='div1'><table id="dtable"></table></div>
#Dilly,
Use this fiddle... As many other answers for the post - you need to create a row once and columns as many times as you wish... so loop for columns not rows. Which also reminds me to tell you - Please don't use loop count variable name as "Row" that is point of confusion. You should name it - numOfColumns for example.
Thanks to the comment, I added this commentary.
https://jsfiddle.net/shemdani/xjpekb94/1/
document.getElementById('dtable').innerHTML = '';
var table = document.getElementById("dtable")
var row = table.insertRow(0);
Rows = 4
for (var count = 0; count < Rows; count++) {
var character = String.fromCharCode(65 + count);
var cell = row.insertCell(count);
cell.innerHTML =('<b>'+character+'</b>');
}

Javascript html table not showing

I've been trying to total a list of die rolls (sum of pairs) in a table using javascript to avoid hard-coding 11 rows in my html page and accessing each row seperately later in the js file to add the values.
So I used a loop and document.writeln() to do this in a more compact way but the output doesn't show the table or anything.
document.writeln("<table border=\"1\"><thead><tr><th>Sum of Dice</th><th>Total Times Rolled</th></tr></thead><tbody>");
for (var i=0; i < 11; i++)
{
document.writeln("<tr><td>2</td><td></td></tr>");
}
document.writeln("</tbody></table>");
The rows shouldn't all start with 2, I only used that number as a test and the second tag in the for loop is for the totals that I already have in an array but my issue is with displaying the table.
Try this:
<script>
var code = "";
function write(){
code += "<table border=\"1\"><tr><th>Sum of Dice</th><th> Total Times Rolled</th></tr>";
for (var i = 0; i < 11; i++){
code += "<tr><td>2</td><td></td></tr>";
}
code += "</table>";
document.body.innerHTML = code;
}
</script>
And don`t forget to put this code to html:
<body onload="write()">
Here you have the result:
I think create table by writeln with whole bunch of HTML text string is generally not a good idea. I would recommend create table dom element via Javascript and append it to the wrapper element.
var headerContent = ['Sum of Dice', 'Total Times Rolled'];
var table = document.createElement('table'),
header = table.createTHead(),
row,
cell;
table.border = 1;
// construct header
row = header.insertRow(0);
for (var i = 0, len = headerContent.length; i < len; i++) {
cell = row.insertCell(i);
cell.innerHTML = headerContent[i];
}
// construct table content
for (var i = 0; i < 11; i++) {
row = table.insertRow(i + 1);
for (var j = 0, len = headerContent.length; j < len; j++) {
cell = row.insertCell(j);
cell.innerHTML = '2';
}
}
// add table element to the dom tree
var wrapper = document.getElementById('wrapper');
wrapper.appendChild(table);
See http://jsfiddle.net/LgyuE/

JavaScript: How to iterate through a table and remove the second cell in Javascript

Lets say that I have a very simple table:
<table>
<tr>
<td>TextFirst</td>
<td>TextSecond</td>
</tr>
</table>
How can I traverse the table and remove "TextSecond". The table could be any number of rows or cells.
In your posted example you have, at least, two options I can think of:
$('td:nth-child(2)').remove();
Or:
$('tr td:eq(1)').remove(); // zero-based index, thanks #ZDYN for the catch
Or, in plain JavaScript:
var removeThis = document.getElementsByTagName('td')[1];
removeThis.parentNode.removeChild(removeThis);
JS Fiddle demo.
$("table td:nth-child(2)").remove()
//var table = document.getElementById("?");
for (i=0; i < table.rows.length; i++)
{
if (table.rows[i].cells.length > 1)
table.rows[i].cells[1].removeNode(true);
}
or if you want to delete cells based on some condition. just because
//var table = document.getElementById("?");
for (i=0; i < table.rows.length; i++)
{
for (j = table.rows[i].cells.length - 1; j >= 0; j--)
{
if (table.rows[i].cells[j].innerHTML == 'TextSecond')
table.rows[i].cells[j].removeNode(true);
}
}
You can use nth-child... :
$('table :nth-child(2)').remove();
JSFIDDLE

Categories

Resources