I have the following function to append rows and cells to an empty table:
function createTable(size) {
var table = document.getElementById("gameTable");
for (var i=0; i<size; i++) {
var tr = document.createElement("tr");
for (var j=0; j<size; j++) {
var td = document.createElement("td");
tr.appendChild(td);
}
table.appendChild(tr);
tr.rowIndex = i;
}
}
So far so good.
My problem is that later, when I tried to reach specific cells inside the table:
var x = target.parentNode.rowIndex;
var y = target.cellIndex;
table.rows[x].cells[y].innerHTML = 'blah'
target is the specific TD that was clicked.
the rows[x] index is always -1. Every time I try the line above I get an error: "cannot read property 'cells' of undefined"
I even tried manually setting the rowIndex of each Row to what it should be (inside the function), but to no avail.
The cellIndex comes out fine, but the rowIndex is -1 and each and every one of the newly created table rows.
What can I do to correct this?
This can be solved by appending the <tr> elements into a <tbody>.
function createTable(size) {
var table = document.getElementById("gameTable");
var tb = document.createElement("tbody");
for (var i=0; i<size; i++) {
var tr = document.createElement("tr");
for (var j=0; j<size; j++) {
var td = document.createElement("td");
tr.appendChild(td);
}
tb.appendChild(tr);
}
table.appendChild(tb);
}
Related
I'm trying to generate a table with 2 rows, with 4 cells each. Each cell is supposed to contain an image. What am I doing wrong? When I call my function, nothing happens.
function generateTable()
{
var table = document.createElement("TABLE");
table.setAttribute("id", "gameBoard");
var row1 = document.createElement("TR");
row1.setAttribute("id", "r1");
table.appendChild(row1);
for (var i = 0; i < 4; i++)
{
var card = document.createElement("TD");
var card_img = document.createElement('img');
card_img.setAttribute("img", "images/card_back.png");
card.appendChild(card_img);
row1.appendChild(card);
}
var row2 = document.createElement("TR");
row2.setAttribute("id", "r2");
table.appendChild(row2);
for (var j = 0; j < 4; j++)
{
var card = document.createElement("TD");
var card_img = document.createElement('img');
card_img.setAttribute("img", "images/card_back.png");
card.appendChild(card_img);
row2.appendChild(card);
}
}
At the end you must do document.appendChild(table);, as you are not adding the element to the page (which you might think you do with document.createElement, but that does not add anything to the DOM).
If you want to add it to a specific element, then I would modify your function to accept a parameter for the id of the div that shall contain your gameboard.
generateTable(elementId) { ... }
and at the end:
let toAdd = document.getElementById(elementId);
toAdd.appendChild(table);
I am building a historical dash (currently with fake data due to security) and I have the multi select list that gens the first name of the person in alphabetic order. Now when selecting one name it regens the table with said name. When I select multiple names, it regens the table with the "lowest" alphabetical name. I cant figure out why my filter function is not building the new array with all selected names that are true in the "selected" statement. However I used the push() function and that works but only shows the first name. Any help would be awesome, I am new to JS and working with DOM is really fun!
histData is the main array with all info,
fNameArr is the re populated array from the filter method given the multi selections
Here is my js:
function mSelList(){
var selName = document.getElementById("jomax");
var fNameArr;
for(i=0; i<selName.length;i++){
let currentName = selName[i];
if(currentName.selected == true){
let fName = currentName.value;
fNameArr = histData.filter(function(data){
return data.first_name == fName;
});
}
}
function createTable(){
var col = [];
for (var i = 0; i < fNameArr.length; i++) {
for (var key in fNameArr[i]) {
if (col.indexOf(key) === -1) {
col.push(key);
}
}
}
// create table section with css filters
var table = document.createElement("table");
table.setAttribute("class", "table is-hoverable is-bordered is-narrow");
table.setAttribute("id", "table");
var tr = table.insertRow(-1);
for (var i = 0; i < col.length; i++) {
var th = document.createElement("th");
th.setAttribute("class", "is-uppercase is-size-7"); // attributes
th.innerHTML = col[i];
tr.appendChild(th);
}
for (var i = 0; i < fNameArr.length; i++) {
tr = table.insertRow(-1);
for (var j = 0; j < col.length; j++) {
var tabCell = tr.insertCell(-1);
tabCell.innerHTML = fNameArr[i][col[j]];
}
}
var tblSec = document.getElementById("tableSec");
tblSec.innerHTML = "";
tblSec.appendChild(table);
}
createTable();
}
You are using getElementById and running a loop over it? getElementById will return one specific element not a list of element. Here is mdn_link for more info.
var selName = document.getElementById("jomax");
I would suggest to use class instead.
I want to add <th> headers to a <table> that does not have an "id" but which is in a <div> having a known "id" so I traverse the DOM to find it:
// search <table>
var c = document.getElementById("tablediv").children;
var i; for(i = 0; i < c.length; i++)
{ Output("- " + c[i].nodeName + "<br>"); // show progress
if(c[i].nodeName == "TABLE") break; }
var tablex = c[i]; // that's the right object
var columns = tablex[0].length; // "TypeError: tablex[0] is undefined"
var row = tablex.insertRow(-1);
for(var i = 0; i < columns; i++)
{ var headerCell = document.createElement("TH");
headerCell.innerHTML = tablex[1][i];
row.appendChild(headerCell);
}
And when tablex[0].length; is run it raises "TypeError: tablex[0] is undefined".
I guess var tablex is an incorrect way to assign c[i];.
Can you please let me know how to do it right?
NOTE: the first TD row of the table contains the column titles so either we convert this row to TH or we fetch titles and delete the TD row after a TH row was inserted.
First of all, you don't need to traverse like that. It's easier to query the table directly with querySelector('#tablediv table'). Notice the use of querySelector instead of querySelectorAll, this returns first table inside the node with requested ID.
So the final code would look like this:
var table = document.querySelector('#tablediv table');
// Here you can add check if the table was found (not null) - I'll leave that to you
var firstRow = table.querySelector('tr');
var columns = firstRow.querySelectorAll('td'); // Or th if you have a header cells
console.log(`Number of columns: ${columns.length}`);
var headerRow = document.createElement('tr');
firstRow.parentNode.insertBefore(headerRow, firstRow);
for(var i = 0; i < columns.length; i++) {
var headerCell = document.createElement("TH");
headerCell.innerHTML = columns[i].innerHTML;
headerRow.appendChild(headerCell);
}
firstRow.remove();
Considering the fact that tablex would optimally be a HTMLTableElement, tablex[0] is not defined.
I have the following javascript that adds a new row to the bottom of a table.
It works fine in Firefox, but it doesn't work in IE (version 8).
There are no visible errors, as far as I can tell.
Any ideas are very helpful!
function addRow() {
// locate the last row in the table
var table = document.getElementById("approversTable");
var rows = document.getElementsByTagName("tr");
var rowToClone;
for (var i=0; i<rows.length; i++) {
if (rows[i].id != "") {
rowToClone = rows[i];
}
}
// clone the row
var clone = rowToClone.cloneNode(true);
var rowId = Math.floor(Math.random()*100000);
clone.id = rowId;
// add the new row to the table
table.appendChild(clone);
}
You should select the table tbody element instead of the table directly.
function addRow() {
var table = document.getElementById("approversTable");
var tbody = table.tbodies[0];
var rows = document.getElementsByTagName("tr");
var rowToClone;
for (var i=0; i<rows.length; i++) {
if (rows[i].id != "") {
rowToClone = rows[i];
}
}
// clone the row
var clone = rowToClone.cloneNode(true);
var rowId = Math.floor(Math.random()*100000);
clone.id = rowId;
// add the new row to the table
tbody.appendChild(clone);
}
more info at: http://www.w3schools.com/jsref/coll_table_tbodies.asp
Is there an easy way to combine rows in an HTML table where the first column is the same? I basically have a table set up like:
<table>
<tr><td>test</td><td>12345</td><td>12345</td><tr>
<tr><td>test</td><td>12345</td><td>12345</td><tr>
<tr><td>test2</td><td>12345</td><td>12345</td><tr>
<tr><td>test</td><td>12345</td><td>12345</td><tr>
<tr><td>test2</td><td>12345</td><td>12345</td><tr>
</table>
and I want it to generate:
<table>
<tr><td>test</td><td>37035</td><td>37035</td><tr>
<tr><td>test2</td><td>24690</td><td>24690</td><tr>
</table>
using jQuery:
var map = {};
$('table tr').each(function(){
var $tr = $(this),
cells = $tr.find('td'),
mapTxt = cells.eq(0).text();
if(!map[mapTxt]){
map[mapTxt] = cells;
} else {
for(var i=1, l=cells.length; i<l; i++){
var cell = map[mapTxt].eq(i);
cell.text(parseInt(cell.text()) + parseInt(cells[i].text()));
}
$tr.remove();
}
});
this is a "dumb" script -- no error handling for cases like different number of cells, fields being non-numeric, etc. Add those if necessary.
Also, depending on how it's generated, it's better to do this server-side.
Here's a plain JavaScript version.
window.onload = function() {
var table = document.getElementById('mytable');
var tr = table.getElementsByTagName('tr');
var combined = Array();
for (i = 0; i < tr.length; i++) {
var td = tr[i].getElementsByTagName('td');
var key = td[0].innerText;
if (!combined[key]) {//if not initialised
combined[key] = Array();
for (j = 0; j < td.length - 1; j++) combined[key][j] = 0;
}
for (j = 0; j < td.length - 1; j++)
combined[key][j] += parseInt(td[j + 1].innerText);
}
while (table.hasChildNodes()) table.removeChild(table.lastChild);
var tbody = document.createElement('tbody');//needed for IE
table.appendChild(tbody);
for (var i in combined) {
tr = document.createElement('tr');
tbody.appendChild(tr);
td = document.createElement('td');
td.innerText = i;
tr.appendChild(td);
for (j = 0; j < combined[i].length; j++) {
td = document.createElement('td');
td.innerText = combined[i][j];
tr.appendChild(td);
}
}
}
This will work on tables with any number of rows and any number of cells. I suppose you want to make the sum for every column, that's what this script does.
And as cwolves mentioned, it is more logical to do this serverside. Users that have JS disabled will see the not so clean uncombined table.