I have a JavaScript generated table the user can interact with. Bellow the table, after generating it, a button should be displayed, so it has the display: none
after init in my css file.
function createTable(row, col, playerNames) {
const tbl = document.getElementById("table")
const tblBody = document.getElementById("tbody")
// Creating cells
for (let i = 0; i < row; i++) {
const row = document.createElement("tr")
for (let j = 0; j < col; j++) {
const cell = document.createElement("td")
if (i == 0 && j == 0) {
// Create "Runden" cell
const cellText = document.createTextNode("Runden")
cell.appendChild(cellText)
} else if (i == 0 && j != 0) {
// Create cells with player names in first row
const cellText = document.createTextNode(playerNames[j])
cell.appendChild(cellText)
} else if (i != 0 && j == 0) {
// Create round counter cells
const cellText = document.createTextNode(String(i))
cell.appendChild(cellText)
} else {
// Create rest of the cells
cell.contentEditable = "true"
}
row.appendChild(cell)
}
if (tblBody) {
tblBody.appendChild(row)
}
}
if (tbl) {
// @ts-ignore
tbl.appendChild(tblBody)
}
// @ts-ignore
document.body.appendChild(tbl)
addSumRowToTable(col)
addEventListenerToTableDataCells()
displayEventCardsButton()
}
function displayEventCardsButton() {
let eventCardButton = document.getElementById("event_cards")
if (eventCardButton) {
eventCardButton.style.display = "block"
}
}
<div id="player_count_heading">Anzahl der Spieler eingeben</div>
<div>
<table id="table">
<tbody id="tbody"></tbody>
</table>
</div>
<div class="buttons">
<button id="player_count" type="button">Spieleranzahl</button>
<button id="event_cards" type="button">Ereigniskarten</button>
</div>
<script src="js/frantic.js"></script>
With this code the button is being displayed after generating the table, but it is always appears above the table. The div of the button is placed bellow and so should the button?
I first created the whole table with javascript, but after I encountered this problem, I tried to solve it by clearly positioning the div containers in the html file. But this is also not working out.
Are there any JavaScript/HTML specific things that leads to this behave?
You are selecting an existing table already:
const tbl = document.getElementById("table")
And because you called this:
document.body.appendChild(tbl) // Remove this
You are moving the table to the bottom on the body, after the buttons.
Unless you are actually creating a table like this:
const tbl = document.createElement("table")
There is no need to append it, and shift its position in the DOM.
Here is an updated snippet. I renamed some variables, called append
instead of appendChild
, and use textContent
to simply your logic.
createTable(10, 5, ["Ann", "Joe", "Mike", "Sam"]);
function createTable(rowCount, colCount, playerNames) {
const table = document.querySelector("#grid");
let tbody = table.querySelector("tbody");
if (tbody == null) {
tbody = document.createElement("tbody");
table.append(tbody);
}
// Populate the table with data
for (let rowIndex = 0; rowIndex <= rowCount; rowIndex++) {
const tr = document.createElement("tr");
for (let colIndex = 0; colIndex < colCount; colIndex++) {
const td = document.createElement("td");
if (rowIndex == 0 && colIndex == 0) {
td.textContent = "Round";
} else if (rowIndex == 0 && colIndex != 0) {
// Create cells with player names in first row
td.textContent = playerNames[colIndex - 1];
} else if (rowIndex != 0 && colIndex == 0) {
// Create round counter cells
td.textContent = rowIndex;
} else {
// Create rest of the cells
td.contentEditable = true;
}
tr.append(td);
}
tbody.append(tr);
}
addSumRowToTable(tbody, colCount);
addEventListenerToTableDataCells();
displayEventCardsButton();
}
function addSumRowToTable(tbody, colCount) {
const tr = document.createElement("tr");
for (let colIndex = 0; colIndex < colCount; colIndex++) {
const td = document.createElement("td");
if (colIndex === 0) {
td.textContent = "Sum";
} else {
td.textContent = "$";
}
tr.append(td);
}
tbody.append(tr);
}
function addEventListenerToTableDataCells() {
// Not implemented
}
function displayEventCardsButton() {
let eventCardButton = document.getElementById("event_cards");
if (eventCardButton) {
eventCardButton.style.display = "block";
}
}
table#grid {
border-collapse: collapse;
}
table#grid, table#grid td {
border: thin solid grey;
}
table#grid td {
padding: 0.25rem;
}
table#grid tr td:first-child {
text-align: right;
}
<div id="player_count_heading">Anzahl der Spieler eingeben</div>
<div>
<table id="grid"></table>
</div>
<div class="buttons">
<button id="player_count" type="button">Spieleranzahl</button>
<button id="event_cards" type="button">Ereigniskarten</button>
</div>
<script src="js/frantic.js"></script>
Although, here is a better way. You should take advantage of <thead>
, <tfoot>
, and <th>
elements as well. Also, if your function is called "createX", it should probably create and return something.
const existingTable = document.querySelector("#grid");
const table = createTable(["Ann", "Joe", "Mike", "Sam"], 10);
table.id = existingTable.id;
existingTable.replaceWith(table);
function createTable(playerNames, rounds) {
const table = document.createElement("table");
const thead = document.createElement("thead");
const tbody = document.createElement("tbody");
const tfoot = document.createElement("tfoot");
const colCount = playerNames.length + 1;
const headerRow = document.createElement("tr");
for (let colIndex = 0; colIndex < colCount; colIndex++) {
const header = document.createElement("th");
header.textContent = colIndex === 0 ? "Round" : playerNames[colIndex - 1];
headerRow.append(header);
}
thead.append(headerRow);
// Populate the table with data
for (let rowIndex = 0; rowIndex < rounds; rowIndex++) {
const tr = document.createElement("tr");
for (let colIndex = 0; colIndex < colCount; colIndex++) {
if (colIndex === 0) {
// Create round counter cells
const th = document.createElement("th");
th.textContent = rowIndex + 1;
tr.append(th);
} else {
// Create rest of the cells
const td = document.createElement("td");
td.contentEditable = true;
tr.append(td);
}
}
tbody.append(tr);
}
table.append(thead);
table.append(tbody);
table.append(tfoot);
addSumRowToTable(tfoot, playerNames.length + 1);
addEventListenerToTableDataCells();
displayEventCardsButton();
return table;
}
function addSumRowToTable(tfoot, colCount) {
const tr = document.createElement("tr");
for (let colIndex = 0; colIndex < colCount; colIndex++) {
if (colIndex === 0) {
// Create round counter cells
const th = document.createElement("th");
th.textContent = "Sum";
tr.append(th);
} else {
// Create rest of the cells
const td = document.createElement("td");
td.textContent = "$";
tr.append(td);
}
}
tfoot.append(tr);
}
function addEventListenerToTableDataCells() {
// Not implemented
}
function displayEventCardsButton() {
let eventCardButton = document.getElementById("event_cards");
if (eventCardButton) {
eventCardButton.style.display = "block";
}
}
table#grid {
border-collapse: collapse;
}
table#grid, table#grid th, table#grid td {
border: thin solid grey;
}
table#grid th, table#grid td {
padding: 0.25rem;
}
table#grid tbody tr th:first-child {
text-align: right;
background: #EEE;
}
table#grid thead {
background: #CCC;
}
table#grid tfoot {
background: #EEE;
}
<div id="player_count_heading">Anzahl der Spieler eingeben</div>
<div>
<table id="grid"></table>
</div>
<div class="buttons">
<button id="player_count" type="button">Spieleranzahl</button>
<button id="event_cards" type="button">Ereigniskarten</button>
</div>
<script src="js/frantic.js"></script>