I have a .js file that creates a 4x4 table that way:
document.write('<div align="center"><table>');
for (var a = 0; a < 4; a++) {
document.write('<tr>');
for (var b = 0; b < 4; b++) {
document.write('<td align="center" id="t' +((4 * a) + b) + '"></td>');
}
document.write('<\/tr>');
}
What if I want to add one column and one row to that table after the page is loaded? In other terms, I'm looking for the same function but the "4" is a variable and I get its value from a checkbox.
(I didn't put that code in a proper function because every time I call document.write in a function, the page goes blank).
Maybe there is another way to use it in a function without document.write and that's what I'm looking for.
So I tried to concat all the '' strings and apply them to the .innerHTML of the table, but it didn't work. Any ideas why? And how can I correct the bug?
Thank you. (No jQuery answers please...)
You can use the standard document methods. Documentation can be found on MDN
CSS
table {
width: 100px;
height: 100px;
border-style: solid;
border-width: 3px;
}
td {
width: 25px;
height: 25px;
border-style: solid;
border-width: 1px;
}
Javascript
var table = document.createElement('table'),
tHead = document.createElement('thead'),
tBody = document.createElement('tbody'),
row,
cell,
a,
b;
table.align = 'center';
table.appendChild(tHead);
table.appendChild(tBody);
for (a = 0; a <= 3; a += 1) {
row = tBody.insertRow(-1);
for (b = 0; b <= 3; b += 1) {
cell = row.insertCell(-1);
cell.id = (4 * a) + b;
cell.align = 'center';
cell.appendChild(document.createTextNode(cell.id));
}
}
document.body.appendChild(table);
On jsFiddle
var main = document.getElementById("table");
document.write('<div align="center" id="table"><table>');
for (var a = 0; a < 4; a++) {
main.appendChild('<tr>');
for (var b = 0; b < 4; b++) {
main.appendChild('<td align="center" id="t' +((4 * a) + b) + '"></td>');
}
main.appendChild('<\/tr>');
}
I'm basically just switching document.write for appendChild(). Does that work for you?
Related
I am working with HTML tables and need to achieve color change in a certain way.
My desired result is as described below.
Lower figure shows that assume current state is upper figure,then cell 1 is clicked,upper figure becomes like lower figure.
I would like to selectfirstelement,and then add 'aqua' class after5cells including first cell.
I achieved to select first cells among these clicked cells,But I couldn't figure out how to detect after 5 cells which has 'class'.
If someone has opinion,please let me know
Thanks
$("td").click(function() {
$(this).addClass("red");
$("td.aqua").removeClass("aqua");
$("td.red").first().addClass("aqua");
});
td {
transition-duration: 0.5s;
border: solid black 1px;
padding: 5px;
cursor:pointer;
}
table {
border-collapse: collapse;
}
.red {
background-color:red;}
.aqua{
background-color:aqua;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id=calendar></div>
<script>
let html = ''
html += '<table>';
let i = 0;
for (let w = 0; w < 5; w++) {
html += '<tr>';
for (let d = 0; d < 10; d++) {
i=i+1;
html += '<td>'+ i+'</td>'
}
html += '</tr>';
}
html += '</table>'
document.querySelector('#calendar').innerHTML = html;
</script>
I'm not 100% sure I understand correctly what you need to do, but this will color the clicked cell in aqua and the following 5 cells in red. Even if it's not exactly what you need, it should guide you in the right direction.
$('body').on('click', "td", function() {
let _this = this;
let _index = -1;
$(this).parents('table').find('td').each(function(i, el){
if(el == _this){
_index = i;
}
if (_index > -1 && i > _index && i < (_index + 6)){
console.log(i);
$(el).addClass('red');
}
});
$(this).addClass("aqua");
});
On a logical level you need to loop through all your td elements and detect which one of them has been clicked, get the index if it and then add the class red to the following 5 elements. Apply class aqua to the clicked one either at the end or at the beginning.
Does this what you want?
$("table").on("click", "td", function(ev) {
$(this).removeClass("aqua").addClass("red");
let nextRowIdx = this.parentNode.rowIndex,
nextCellIdx = this.cellIndex + 5;
if (nextCellIdx >=10) {
nextRowIdx += 1;
nextCellIdx -= 10;
}
try {
let tbl = this.parentNode.parentNode,
cell = tbl.children[nextRowIdx].children[nextCellIdx];
$(cell).removeClass("red").addClass("aqua");
} catch (err) {
}
});
td {
transition-duration: 0.5s;
border: solid black 1px;
padding: 5px;
cursor:pointer;
}
table {
border-collapse: collapse;
}
.red {
background-color:red;}
.aqua{
background-color:aqua;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id=calendar></div>
<script>
let html = ''
html += '<table>';
let i = 0;
for (let w = 0; w < 5; w++) {
html += '<tr>';
for (let d = 0; d < 10; d++) {
i=i+1;
html += '<td>'+ i+'</td>'
}
html += '</tr>';
}
html += '</table>'
document.querySelector('#calendar').innerHTML = html;
</script>
I want the onclick function to remember the value of the variable i and j in the for loop at the instance the onclick function is called. However the variables update before they are stored in the onclick function.
I am making a Tic Tac Toe application and don't want to manually add all the onclick statements as that would be a bad practice for larger projects.
for (j = 0; j < Columns; j++) {
var col = document.createElement("td")
row.appendChild(col)
col.id = i + "" + j;
col.onclick = function() {
console.log(i, j)
place(i + "" + j)
}
}
There are no error messages but I don't know how to save the variables the instance the onclick function is called. How can I save the variables when the onclick function is called?
You must scope your variables declaring it by the use of let, that way you'll scope it exclusively for that iteration. Avoid to declare a variable like i = 0, bacause that way you create a global variable and it will not work (throw an error) on 'use strict' cases.
let Columns = 3
let rows = 3
const table = document.getElementById("table")
for (let i = 0; i < rows; i++) {
let row = document.createElement("tr");
row.textContent = "row " + i;
table.appendChild(row)
for (let j = 0; j < Columns; j++) {
var col = document.createElement("td")
row.appendChild(col)
col.id = i + "" + j;
col.onclick = function() {
console.clear()
console.log(i, j)
}
}
}
tr, td{
border: 1px solid;
min-height: 60px;
min-width: 60px;
}
<table id="table"></table>
If you can't use let (maybe because it is ES6), you can use the common var, but then you'll need to bind the values on the function, as the code below shows:
var Columns = 3
var rows = 3
var table = document.getElementById("table")
for (var i = 0; i < rows; i++) {
var row = document.createElement("tr");
row.textContent = "row " + i;
table.appendChild(row)
for (var j = 0; j < Columns; j++) {
var col = document.createElement("td")
row.appendChild(col)
col.id = i + "" + j;
col.onclick = function(rowI, colJ) {
console.clear()
console.log(rowI, colJ)
}.bind(this, i, j) //bind parameters -> this is the context
}
}
tr, td{
border: 1px solid;
min-height: 60px;
min-width: 60px;
}
<table id="table"></table>
Could anyone help me make a multiplication table, 0-10 in an 11x11 table?
I need to use createElement/appendchild. When I use document write, it almost look complete, just miss the placement of the blue columns/rows.
It should look something like this (Only need the numbers, no fancy outline):
This is what I've got so far:
for(var i = 0; i < 1; i++){
var tabell1 = document.createElement("table");
tabell.appendChild(tabell1);
//document.write("<table>");
for(var j = 0; j<11; j++){
var rad = document.createElement("tr");
tabell.appendChild("tr");
//document.write("<tr>");
for(var k = 1; k<=11; k++){
var kolonne = document.createElement("td");
tabell.appendChild(kolonne);
kolonne.innerHTML = k*(j+1);
//document.write("<td>"+ k*(j+1) +"</td>");
}
//document.write("</tr>");
}
//document.write("</table>")
}
<div id="tabell"></div>
You can generate the table using two loops.
You iterate twice from 0 to 10 included.
Use use the value 0 to represent your top row and first column, which hold the numbers to be multiplied. Since the iterator starts at 0, the value will be 0 and you can use that to detect when to add the header class and set the value to your non-zero iterator, either i or j:
const table = document.createElement('table');
for (let i = 0; i <= 10; i++){
const row = document.createElement('tr');
for (let j = 0; j <= 10; j++){
const col = document.createElement('td');
let val = i * j;
if (val === 0) {
val = i || j;
val = val ? val : '';
col.classList.add('header');
}
col.innerHTML = val;
row.appendChild(col);
}
table.appendChild(row);
}
document.body.appendChild(table);
table {
border-collapse: collapse;
}
td {
border: 1px solid black;
padding: 3px;
text-align: center;
}
.header {
background: #ccf;
}
The blue border can be obtained by css. See my code. I only changed four lines of loop
function createTables(maxNum,limit){
const table = document.createElement('table');
for(let i = 0;i<maxNum + 1;i++){
const row = document.createElement('tr');
for(let j = 0;j<limit + 1;j++){
const td = document.createElement('td');
//Below four lines are new
if(i === 0 && j === 0) td.innerHTML = '';
else if(i === 0) td.innerHTML = j;
else if(j === 0) td.innerHTML = i;
else td.innerHTML = i*j;
row.appendChild(td);
}
table.appendChild(row)
}
document.body.appendChild(table)
}
createTables(10,15);
table{
border-collapse:collapse;
}
td{
padding:20px;
font-size:25px;
background-color:gray;
border:2px solid black;
text-align:center;
vertical-align:center;
color:white;
}
tr > td:nth-child(1),tr:nth-child(1) > td{
background:blue;
}
I think best to use inserRow and insertCell
Cheers!
for (var i = 0; i < 1; i++) {
var tabell1 = document.createElement("table");
tabell.appendChild(tabell1);
for (var j = 0; j < 11; j++) {
var row = tabell1.insertRow(j);
for (var k = 0; k <= 10; k++) {
var cell = row.insertCell(k);
if (j == 0 && k == 0) {
//if first row and first column do nothing
} else if (j == 0) {
//else if first row
cell.innerHTML = k * (j + 1);
} else if (k == 0) {
//else if first column
cell.innerHTML = j;
} else {
//else multiply
cell.innerHTML = k * (j);
}
}
}
}
<div id="tabell"></div>
I would like to create diagonal in my table. For example if i have table 5x5 i have to grab first row and first column in this row and set background of thic column to be red. For the second row i have to do the same on second column in second row.
var cols = 6,
rows = 6;
for (r = 0; r < rows; r++) {
var row = $('<tr></tr>')
$('table').append(row);
for (c = 0; c < cols; c++) {
var col = $('<td></td>');
row.append(col);
$(col[r][c]).addClass('kolorek')
}
}
table td {
width: 20px;
height: 20px;
border: 1px solid;
}
.kolorek {
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
</table>
Here is a fiddle
You're almost there.
var cols = 6,
rows = 6,
$table = $('table'); // Caching the table, because this will be called many times (perf improvement)
for (r = 0; r < rows; r++) {
var row = $('<tr></tr>')
for(c = 0; c < cols; c++){
var col = $('<td></td>')
if(c==r) col.addClass('kolorek') // col[r][c] is undefined. This matches the same column and row numbers
row.append(col)
}
$table.append(row);
}
table td {
width: 20px;
height: 20px;
border: 1px solid;
}
.kolorek {
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table></table>
You can just check if the row index equals the column index to make a diagonal line from left top to right bottom:
var cols = 6,
rows = 6;
for (r = 0; r < rows; r++) {
var row = $('<tr></tr>')
$('table').append(row);
for (c = 0; c < cols; c++) {
var col = $('<td></td>');
row.append(col);
if (r == c) col.addClass('kolorek'); // add this in place of your current kolerik adder
}
}
table td {
width: 20px;
height: 20px;
border: 1px solid;
}
.kolorek {
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
</table>
I am trying to create board game (like chess board game) with JavaScript.
When I tried to do it this is what happened:
The <tr> got closed immediately with </tr>, same thing with <table> </table>
I tried to replace the append() method with appendTo() or add() but it didn't help
This is my JavaScript code:
var boardSize = 5;
$(function() { //on load
printBoard(boardSize);
});
function printBoard(i_BoardSize) {
var maxRow = parseInt(i_BoardSize);
var maxCol = parseInt(i_BoardSize);
var num = 1;
$("#board").append("<table oncontextmenu=\"return false\">");
for(var row = maxRow - 1; row >= 0 ; row--) {
$("#board").append("<tr>");
for(var col = 0; col < maxCol ; col++) {
$("#board").append("<td>" + num + "</td>");
num++;
}
$("#board").append("</tr>");
}
$("#board").append("</table>");
}
CSS:
td {
width: 32px;
height: 32px;
cursor: pointer;
text-align: center;
border: 2px solid blue;
}
.redborder {
background-color: red;
color: white;
}
.blueborder {
background-color: blue;
color: white;
}
HTML:
<!DOCTYPE html>
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel='stylesheet' type='text/css' href='css/board.css' />
<script type="text/javascript" src="jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="Scripts/board.js"></script>
</head>
<body>
<p> <center><h3><font size="20" color="black"> Board Game</font></h3></center></p>
<div>
<div id="board">
<div class="cell">
</div>
</div>
</div>
</body>
</html>
This happens because jQuery append() method not supporting only closing tags and trying to close tags if they wasn't closed in provided param. To solve this you need to assign your append() result to some variable, for example:
var myTable = $("<table oncontextmenu=\"return false\"></table>").appendTo("#board");
and then append your rows to this var:
var myRow = $("<tr></tr>").appendTo( myTable );
Same with columns:
myRow.append("<td>" + num + "</td>");
By using appendTo method you will be able to get newly created elements.
So your final code should look like:
var boardSize = 5;
$(function() { //on load
printBoard(boardSize);
});
function printBoard(i_BoardSize) {
var maxRow = parseInt(i_BoardSize);
var maxCol = parseInt(i_BoardSize);
var num = 1;
var myTable = $("<table oncontextmenu=\"return false\"></table>").appendTo("#board");
for (var row = maxRow - 1; row >= 0; row--) {
var myRow = $("<tr></tr>").appendTo(myTable);
for (var col = 0; col < maxCol; col++) {
myRow.append("<td>" + num + "</td>");
num++;
}
}
}
The others have supplied you with why this is happening but I thought I might give an example of how you might make better use of css and more recent dom usage.
Fiddle: http://jsfiddle.net/np62shu6/1/
But the basic idea is to define the number of cells, then write out a series of divs that have a 20% float value. In the end you have a chess board with a cell data attribute.
HTML:
<div id="game">
</div>
CSS:
.cell{
width:20%;
float:left;
text-align:center;
}
.odd{
background:#eee;
}
JS (assumed you place this in a load handler):
var cells = 25;
var cell;
var h;
for(var i = 1; i <= cells; i ++)
{
cell = $('<div>').addClass('cell').attr('data-cell', i).text(i);
if(i % 2 == 1)
cell.addClass('odd');
$('#game').append(cell);
}
h = $('.cell:last-of-type').width();
$('.cell').css({height: h, lineHeight: h + 'px'});
As others have said, append is a sequential method, so calling it one after the other will just keep dropping things in the DOM. But you can create elements, then add things to those elements using append, then use append to add that whole group to another...
My example does not show this. My example is just an alternative to what you wrote. I would not do it the way you are doing it is all.
Another slight side note - chess boards have 64 cells (8 x 8), but I left it at 25 because your example did this.
When you append a tag with jQuery it doesn't work like appending text to a HTML string. Instead it creates the dom element. Try something like this instead, notice the absence of closing tags and td is appended directly to the latest tr:
var boardSize = 5;
$(function() { //on load
printBoard(boardSize);
});
function printBoard(i_BoardSize)
{
var maxRow = parseInt(i_BoardSize);
var maxCol = parseInt(i_BoardSize);
var num = 1;
$("#board").append("<table oncontextmenu=\"return false\">");
for(var row = maxRow - 1; row >= 0 ; row--)
{
$("#board table").append("<tr>");
for(var col = 0; col < maxCol ; col++)
{
$("#board tr:last").append("<td>" + num + "</td>");
num++;
}
}
}
The error is here:
function printBoard(i_BoardSize)
{
var maxRow = parseInt(i_BoardSize);
var maxCol = parseInt(i_BoardSize);
var num = 1;
$("#board").append("<table oncontextmenu=\"return false\">");
for(var row = maxRow - 1; row >= 0 ; row--)
{
#here
$("#board").append("<tr>");
for(var col = 0; col < maxCol ; col++)
{
#here
$("#board").append("<td>" + num + "</td>");
num++;
}
$("#board").append("</tr>");
}
$("#board").append("</table>");
}
You are appending each element to the #board instead of properly nesting them. try keeping the created elements in variables, and do nesting:
function printBoard(i_BoardSize)
{
var maxRow = parseInt(i_BoardSize);
var maxCol = parseInt(i_BoardSize);
var num = 1;
$tableelement = $("<table oncontextmenu=\"return false\"></table>");
$("#board").append($tableelement);
for(var row = maxRow - 1; row >= 0 ; row--)
{
#here
$rowelement = $("<tr></tr>");
$tableelement.append($rowelement);
for(var col = 0; col < maxCol ; col++)
{
#here
$rowelement.append("<td>" + num + "</td>");
num++;
}
}
}
Reason: certain browsers will immediately try to fix malformed HTML, and in the middle of the execution, the items are malformed while you insert it, and are wellformed after you finish. in the middle -this function's execution is not atomic- the code is malformed and the browser tries to fix it by closing the tags you add. That's why you need to add elements by nesting -opening and closing the tags for them beforehand-
$(function() { //on load
var boardSize = 5;
printBoard(boardSize);
});
function printBoard(i_BoardSize)
{
var maxRow = parseInt(i_BoardSize),
maxCol = maxRow;
var $table = $("<table oncontextmenu='return false'></table>").appendTo($("#board"));
for(var row = 1; row <= maxRow; row++)
{
var $row = $("<tr/>").appendTo($table);
for(var col = 1; col <= maxCol; col++)
{
$row.append("<td>" + (row*col) + "</td>");
}
}
}
td {
width: 32px;
height: 32px;
cursor: pointer;
text-align: center;
border: 2px solid blue;
}
.redborder {
background-color: red;
color: white;
}
.blueborder {
background-color: blue;
color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p> <center><h3><font size="20" color="black"> Board Game</font></h3></center></p>
<div>
<div id="board">
<div class="cell">
</div>
</div>
</div>
Side note: You don't have to append the closing tags manually...
This is way easier and cleaner if you just learn JavaScript and work in the DOM.
function makeBoardWithoutJQuery(xs, ys) {
var table = document.createElement('table');
var tbody = document.createElement('tbody');
for (var y=0; y<ys; ++y) {
var tr = document.createElement('tr');
for (var x=0; x<xs; ++x) {
var td = document.createElement('td');
td.innerHTML = (y*xs) + x;
tr.appendChild(td);
}
tbody.appendChild(tr);
}
table.appendChild(tbody);
return table;
}