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;
}
Related
So far I have created the code to generate a table that has the number of cells that is defined by the user. In addition to this, the cells which have the prime numbers in it, must be coloured in a different colour. I have also included a function to find the prime numbers, but the approach I took to create the table, doesn't give me an option to implement the function onto the html body.
I would really appreciate any help.
Here's my code..
<html>
<head>
<style>
table{width: 70%;}
</style>
<script>
const numString= window.prompt("What is the loop maximum.? (between 1 and 500)")
let num=parseInt(numString);
if(num<0 || num>500)
{
window.alert("Warning! Must be between 1 and 500. Setting to default
100")
num=100
}
function isPrime(num)
{
for(var i=2; i< num; i++)
if(num % i ===0) return false;
return num>1;
}
</script>
</head>
<body>
<h1>Javascript Loops and Functions</h1><br>
<script>
document.write("<table border=1>");
let rows = num % 10 >= 0 && num % 10 <= 10 ? num / 10 + 1 : num / 10;
let count = 0;
for (row = 1; row <= rows; row++) {
document.write("<tr>");
for (let i = 1; i <= 10; i++) {
if (count >= num+1) break;
document.write("<td>" + count + "</td>");
count++;
}
document.write("</tr>");
}
document.write("</table>");
</script>
</body>
You can use a CSS class to give colors. For instance prime_true could be the class for prime numbers and prime_false for non-primes.
It is not so good practice to use document.write for such a purpose. So I would suggest to have an empty table element in your HTML, and then use loops to populate that table with rows and cells:
function isPrime(num) {
for(var i=2; i< num; i++)
if(num % i ===0) return false;
return num>1;
}
let table = document.querySelector("table");
for (let line = 1; line <= 500; line += 10) {
let row = table.insertRow();
for (let i = line; i < line + 10; i++) {
let td = row.insertCell();
td.textContent = i;
td.className = "prime_" + isPrime(i);
}
}
table { width: 70%; }
td { border: 1px solid; text-align: center }
.prime_true { background: orange }
.prime_false { background: lightgrey }
<h1>Javascript Loops and Functions</h1><br>
<table></table>
NB: this script should be in a script element that is put below the table element.
for (let i = 1; i <= 10; i++) {
if (count >= num+1) break;
if(isPrime(count)){
document.write("<td style='background-color:red'>" + count + "</td>");
} else {
document.write("<td>" + count + "</td>");
}
count++;
}
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>
Every time I click on a cell in a grid, it logs an array of [rows,column] of the cell into a variable, either bla (for black) or whi (for white). However, the next time I click on a cell, it changes the variable. For example, I click on a cell and variable whi is [1,2] then I click on another cell, variable bla is [2,2] and after that, I click on a third cell and variable whi is changed from [1,2] (from the original click) to [3,2]. (I made up random numbers for this). I want to create two 2D arrays, one for the variable bla and one for the variable whi. Using my example, one of the 2D arrays should be [[1,2],[3,2]] (for the white cells) and the other one should be [[2,2]] (for the black cells)
Test out the code:
var white=true;
function generateGrid( rows, cols ) {
var grid = "<table>";
for ( row = 1; row <= rows; row++ ) {
grid += "<tr>";
for ( col = 1; col <= cols; col++ ) {
grid += "<td></td>";
}
grid += "</tr>";
}
return grid;
}
$( "#tableContainer" ).append( generateGrid( 10, 10) );
$( "td" ).click(function() {
$(this).css('cursor','default');
var index = $( "td" ).index( this );
var row = Math.floor( ( index ) / 10) + 1;
var col = ( index % 10) + 1;
var $td = $(this);
if ($td.data('clicked'))
return;
if (white===true){
var whi=[row,col]; //I want to log the array for whi into a 2D array
console.log("white coord is "+whi);
} else {
var bla=[row,col]; //I want to log this array into another 2D array
console.log("black coord is "+bla);
}
$td.data('clicked', true);
$td.css('background-color', white ? 'white' : 'black');
white = !white;
});
html{
background-color:#7189ea;
}
td {
border: 1px solid;
width: 25px;
height: 25px;
border-radius:100%;
}
table {
border-collapse: collapse;
}
<link type="text/css" rel="stylesheet" href="stylesheet.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div id="tableContainer"></div>
Initialize whi and bla as arrays and push [row,col] to them - see demo below:
var white = true;
var whi = [];
var bla = [];
function generateGrid(rows, cols) {
var grid = "<table>";
for (row = 1; row <= rows; row++) {
grid += "<tr>";
for (col = 1; col <= cols; col++) {
grid += "<td></td>";
}
grid += "</tr>";
}
return grid;
}
$("#tableContainer").append(generateGrid(10, 10));
$("td").click(function() {
$(this).css('cursor', 'default');
var index = $("td").index(this);
var row = Math.floor((index) / 10) + 1;
var col = (index % 10) + 1;
var $td = $(this);
if ($td.data('clicked'))
return;
if (white === true) {
whi.push([row, col]);
} else {
bla.push([row, col]);
}
$td.data('clicked', true);
$td.css('background-color', white ? 'white' : 'black');
white = !white;
});
$('#getarr').click(function(){
console.log("white arr: ", whi);
console.log("black arr: ", bla);
});
html {
background-color: #7189ea;
}
td {
border: 1px solid;
width: 25px;
height: 25px;
border-radius: 100%;
}
table {
border-collapse: collapse;
}
<link type="text/css" rel="stylesheet" href="stylesheet.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div id="tableContainer"></div>
<button id="getarr">Get array</button>
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?
Please see the below code, the table should change the number of rows based on input selected in the selected id option below, but only the first value of select id is read, and the number of rows are not changing based on the selection, can you please point out the mistake in my code ?
http://jsfiddle.net/uTY6n/14/
HTML:
<div id="scrollingDiv">
<select id="read">
<option value="1">1</option>
<option value="2">2</option></select>
<table id="contentTable" border="1">
<!-- Fill table programmatically -->
</table>
</div>
JAVASCRIPT:
function buildTable()
{
var myTable =document.getElementById("contentTable");
var j=document.getElementById("read").value;
var rows = [];
var cells = [];
for( var i = 0; i < j; i++ )
{
rows[i] = myTable.insertRow(i);
if(i%3==2)rows[i].addClass("everyrow");
cells[i] = [];
for( var x = 0; x < 3 ; x++ )
{
cells[i][x] =document.createElement((x==0)?"th":"td");
cells[i][x].innerHTML = (x==0)?"<input>":"<input>";
rows[rows.length - 1].appendChild(cells[i][x]);
}
}
}
buildTable();
CSS:
#scrollingDiv
{
border: 1px groove black;
height: 350px;
width: 350px;
background: #ffffff;
overflow: auto;
}
#contentTable
{
height: 350px;
width: 350px;
}
.every3rdrow{
border-bottom:3px solid black;
}
See this demo.
First, you need to attach an event listener to the <select>:
document.getElemenyById('read').addEventListener('change', buildTable);
Then, you need to make sure the table is emptied before it's rebuilt every time buildTable() is called:
function buildTable() {
var myTable =document.getElementById("contentTable");
var j=document.getElementById("read").value;
var rows = [];
var cells = [];
while (myTable.hasChildNodes()) {
myTable.removeChild(myTable.lastChild);
}
...
}
Hope this helps!
try
function buildTable() {
var myTable =document.getElementById("contentTable");
myTable.innerHTML = "";
var j=document.getElementById("read").value;
var rows = [];
var cells = [];
var myHtml = "";
for( var i = 0; i < j; i++ ) {
myHtml += "<tr>";
for( var x = 0; x < 3 ; x++ ){
myHtml += "<td></td>"
}
myHtml += "</tr>";
}
myTable.innerHTML = myHtml;
}
thats the general idea, also be sure to call this onChange of your select.