Code CHESS in JavaScript (Super simple!)

Hello!

I’m trying to code along with Ania but for some reason my project is not looking like hers when. I can’t figure out what i have done wrong since I’m pretty much copying her step by step.

const playerDisplay = document.querySelector("#player");
const infoDisplay = document.querySelector("#info-display");
const width = 8; 
const startPieces = [
    rook, knight, bishop, queen, king, bishop, knight, rook,
    pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
    '', '', '', '', '', '', '', '',
    '', '', '', '', '', '', '', '',
    '', '', '', '', '', '', '', '',
    '', '', '', '', '', '', '', '',
    pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
    rook, knight, bishop, queen, king, bishop, knight, rook,
]

function createBoard(){
    startPieces.forEach((startPiece, i) => {
        const square = document.createElement('div')
        square.classList.add('square')
        square.innerHTML = startPiece
        square.setAttribute('square-id', i)
        //square.classList.add('beige')
        const row = Math.floor((63-i)/8) + 1
        if (row %2 === 0){
            square.classList.add(i % 2 === 0 ? "beige" : "brown")
        }
        else {
            square.classList.add(i % 2 === 0 ? "brown" : "beige")
        }
        if ( i <= 15){
            square.firstChild.firstChild.classList.add('black')
        }

        if ( i >= 48){
            square.firstChild.firstChild.classList.add('white')
        }
        
        gameboard.append(square)   
    })
}
createBoard();

    width: 320px;
    height: 320px;
    display: flex;
    flex-wrap: wrap;
}

.square {
    height: 40px;   
    width: 40px;
}

.beige {
    background-color: rgb(110, 110, 98);
}

.brown {
    background-color: rgb(169, 43, 43);
}

.black {
    fill: rgb(28, 28, 28);
}

.white {
    fill: rgb(255, 255, 255);
}

.square svg {
    height: 30px;
    width: 30px;
    margin: 5px;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Chess</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div id="gameboard"></div>
    <script src="pieces.js"></script>
    <script src="app.js"></script>
    
    <p>It is <span id="player"></span> go.</p>
    <p id="info-display"></p>
</body>
</html>
const king = '<div class ="piece" id="king"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.7.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M248 24c0-13.3-10.7-24-24-24s-24 10.7-24 24l0 32-32 0c-13.3 0-24 10.7-24 24s10.7 24 24 24l32 0 0 40L59.6 144C26.7 144 0 170.7 0 203.6c0 8.2 1.7 16.3 4.9 23.8L59.1 352l52.3 0L49 208.2c-.6-1.5-1-3-1-4.6c0-6.4 5.2-11.6 11.6-11.6L224 192l164.4 0c6.4 0 11.6 5.2 11.6 11.6c0 1.6-.3 3.2-1 4.6L336.5 352l52.3 0 54.2-124.6c3.3-7.5 4.9-15.6 4.9-23.8c0-32.9-26.7-59.6-59.6-59.6L248 144l0-40 32 0c13.3 0 24-10.7 24-24s-10.7-24-24-24l-32 0 0-32zM101.2 432l245.6 0 16.6 32L84.7 464l16.6-32zm283.7-30.7c-5.5-10.6-16.5-17.3-28.4-17.3l-265 0c-12 0-22.9 6.7-28.4 17.3L36.6 452.5c-3 5.8-4.6 12.2-4.6 18.7C32 493.8 50.2 512 72.8 512l302.5 0c22.5 0 40.8-18.2 40.8-40.8c0-6.5-1.6-12.9-4.6-18.7l-26.5-51.2z"/></svg></div>'

const queen = '<div class ="piece" id="queen"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M256 0a56 56 0 1 1 0 112A56 56 0 1 1 256 0zM134.1 143.8c3.3-13 15-23.8 30.2-23.8c12.3 0 22.6 7.2 27.7 17c12 23.2 36.2 39 64 39s52-15.8 64-39c5.1-9.8 15.4-17 27.7-17c15.3 0 27 10.8 30.2 23.8c7 27.8 32.2 48.3 62.1 48.3c10.8 0 21-2.7 29.8-7.4c8.4-4.4 18.9-4.5 27.6 .9c13 8 17.1 25 9.2 38L399.7 400 384 400l-40.4 0-175.1 0L128 400l-15.7 0L5.4 223.6c-7.9-13-3.8-30 9.2-38c8.7-5.3 19.2-5.3 27.6-.9c8.9 4.7 19 7.4 29.8 7.4c29.9 0 55.1-20.5 62.1-48.3zM256 224s0 0 0 0s0 0 0 0s0 0 0 0zM112 432l288 0 41.4 41.4c4.2 4.2 6.6 10 6.6 16c0 12.5-10.1 22.6-22.6 22.6L86.6 512C74.1 512 64 501.9 64 489.4c0-6 2.4-11.8 6.6-16L112 432z"/></svg></div>'

const rook = '<div class ="piece" id="rook"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.7.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M32 192L32 48c0-8.8 7.2-16 16-16l64 0c8.8 0 16 7.2 16 16l0 40c0 4.4 3.6 8 8 8l32 0c4.4 0 8-3.6 8-8l0-40c0-8.8 7.2-16 16-16l64 0c8.8 0 16 7.2 16 16l0 40c0 4.4 3.6 8 8 8l32 0c4.4 0 8-3.6 8-8l0-40c0-8.8 7.2-16 16-16l64 0c8.8 0 16 7.2 16 16l0 144c0 10.1-4.7 19.6-12.8 25.6L352 256l16 144L80 400 96 256 44.8 217.6C36.7 211.6 32 202.1 32 192zm176 96l32 0c8.8 0 16-7.2 16-16l0-48c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 48c0 8.8 7.2 16 16 16zM22.6 473.4L64 432l320 0 41.4 41.4c4.2 4.2 6.6 10 6.6 16c0 12.5-10.1 22.6-22.6 22.6L38.6 512C26.1 512 16 501.9 16 489.4c0-6 2.4-11.8 6.6-16z"/></svg></div>'

const bishop = '<div class ="piece" id="bishop"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--!Font Awesome Free 6.7.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M128 0C110.3 0 96 14.3 96 32c0 16.1 11.9 29.4 27.4 31.7C78.4 106.8 8 190 8 288c0 47.4 30.8 72.3 56 84.7L64 400l192 0 0-27.3c25.2-12.5 56-37.4 56-84.7c0-37.3-10.2-72.4-25.3-104.1l-99.4 99.4c-6.2 6.2-16.4 6.2-22.6 0s-6.2-16.4 0-22.6L270.8 154.6c-23.2-38.1-51.8-69.5-74.2-90.9C212.1 61.4 224 48.1 224 32c0-17.7-14.3-32-32-32L128 0zM48 432L6.6 473.4c-4.2 4.2-6.6 10-6.6 16C0 501.9 10.1 512 22.6 512l274.7 0c12.5 0 22.6-10.1 22.6-22.6c0-6-2.4-11.8-6.6-16L272 432 48 432z"/></svg></div>'

const pawn = '<div class ="piece" id="pawn"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--!Font Awesome Free 6.7.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M215.5 224c29.2-18.4 48.5-50.9 48.5-88c0-57.4-46.6-104-104-104S56 78.6 56 136c0 37.1 19.4 69.6 48.5 88L96 224c-17.7 0-32 14.3-32 32c0 16.5 12.5 30 28.5 31.8L80 400l160 0L227.5 287.8c16-1.8 28.5-15.3 28.5-31.8c0-17.7-14.3-32-32-32l-8.5 0zM22.6 473.4c-4.2 4.2-6.6 10-6.6 16C16 501.9 26.1 512 38.6 512l242.7 0c12.5 0 22.6-10.1 22.6-22.6c0-6-2.4-11.8-6.6-16L256 432 64 432 22.6 473.4z"/></svg></div>'

const knight = '<div class ="piece" id="knight"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.7.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M96 48L82.7 61.3C70.7 73.3 64 89.5 64 106.5l0 132.4c0 10.7 5.3 20.7 14.2 26.6l10.6 7c14.3 9.6 32.7 10.7 48.1 3l3.2-1.6c2.6-1.3 5-2.8 7.3-4.5l49.4-37c6.6-5 15.7-5 22.3 0c10.2 7.7 9.9 23.1-.7 30.3L90.4 350C73.9 361.3 64 380 64 400l320 0 28.9-159c2.1-11.3 3.1-22.8 3.1-34.3l0-14.7C416 86 330 0 224 0L83.8 0C72.9 0 64 8.9 64 19.8c0 7.5 4.2 14.3 10.9 17.7L96 48zm24 68a20 20 0 1 1 40 0 20 20 0 1 1 -40 0zM22.6 473.4c-4.2 4.2-6.6 10-6.6 16C16 501.9 26.1 512 38.6 512l370.7 0c12.5 0 22.6-10.1 22.6-22.6c0-6-2.4-11.8-6.6-16L384 432 64 432 22.6 473.4z"/></svg></div>'````

I’m stuck at this part:

            square.firstChild.firstChild.classList.add('black')
        }

        if ( i >= 48){
            square.firstChild.firstChild.classList.add('white')
        }
        ```

This is the error that i’m getting

app.js:32 Uncaught TypeError: Cannot read properties of undefined (reading 'add')
    at app.js:32:52
    at Array.forEach (<anonymous>)
    at createBoard (app.js:17:17)
    at app.js:42:1```

Also, is there a way here to just add the individual files instead of copy pasting each files contents and using backticks? Thanks!

do you have a timestamp to check?

instead of pasting here the code you can share a github repo

oh, right, you have a space in the king div before the svg, so firstChild is text. To avoid this you could use firstElementChild

Thanks, that did the trick by just getting rid of the space, I must have accidentally pressed the space bar.

1 Like

What do you mean by timestamp? Should I just share a link to my github repo or add anything else?

timestamp of the video, to confront with your code

1 Like

The link i shared has a timestamp with the code, when you open the link it goes straight to the part in youtube that I was having problems with.

Hello, I need some help again, getting the following error app.js:6 Uncaught TypeError: Cannot set properties of null (setting 'textContent') at app.js:6:27

Here is a link to the github repo:
Chess Game Repo

in the html file the script is before the element, so the element doesn’t exist yet when the script runs
possible solutions:

  • use defer attribute on the script
  • OR move the script to just before </body>

That make sense, thanks!

Is this something to be concerned about? If so, how do I fix it?

```Content Security Policy of your site blocks the use of ‘eval’ in JavaScript`
The Content Security Policy (CSP) prevents the evaluation of arbitrary strings as JavaScript to make it more difficult for an attacker to inject unathorized code on your site.

To solve this issue, avoid using eval(), new Function(), setTimeout([string], …) and setInterval([string], …) for evaluating strings.

If you absolutely must: you can enable string evaluation by adding unsafe-eval as an allowed source in a script-src directive.

:warning: Allowing string evaluation comes at the risk of inline script injection.

1 directive
Source location Directive Status
script-src blocked
Learn more: Content Security Policy - Eval

there is written how

if you use eval to execude code from an input, it is a security risk as it can execute malicious code, I don’t think your project is a risk, but it’s always a thing to consider, above all if your site deal with private user info

Thanks, I’m stuck now, the functionality of “you cannot go here” is not working.

        // //must check this first
        // if(takenByOpponent && valid){
        //     e.target.parentNode.append(draggedElement)
        //      e.target.remove()
        //      changePlayer()
        //      return
        // } 
        // then check this
        if (taken && !takenByOpponent) {
            infoDisplay.textContent = "you cannot go here!"
            setTimeout(() => infoDisplay.textContent = "", 2000)
            return
        } 
    }
    ```

please provide a timestamp for the video, and line number and filename for the github repo

49:20 timestamp,
Lines 74-88,

I’m not so good with Github and I just manually updated the file app.js but for some reason the updated version is not showing, instead it shows…

const fs = require('fs')

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'content-type': 'text/html' })
  fs.createReadStream('index.html').pipe(res)
})

console.log('Server running at http://localhost:3000/')

server.listen(process.env.PORT || 3000)``` 

However, when I click on add files via upload this is what is see 
```const gameboard = document.querySelector("#gameboard");
const playerDisplay = document.querySelector("#player");
const infoDisplay = document.querySelector("#info-display");
const width = 8; 
let playerGo = 'black'
playerDisplay.textContent = 'black'
const http = require('http')
const fs = require('fs')

const startPieces = [
    rook, knight, bishop, queen, king, bishop, knight, rook,
    pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
    '', '', '', '', '', '', '', '',
    '', '', '', '', '', '', '', '',
    '', '', '', '', '', '', '', '',
    '', '', '', '', '', '', '', '',
    pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
    rook, knight, bishop, queen, king, bishop, knight, rook,
]

function createBoard(){
    startPieces.forEach((startPiece, i) => {
        const square = document.createElement('div')
        square.classList.add('square')
        square.innerHTML = startPiece
        square.firstChild?.setAttribute('draggable', true)
        square.setAttribute('square-id', i)
        //square.classList.add('beige')
        const row = Math.floor((63-i)/8) + 1
        if (row %2 === 0){
            square.classList.add(i % 2 === 0 ? "beige" : "brown")
        }
        else {
            square.classList.add(i % 2 === 0 ? "brown" : "beige")
        }
        if ( i <= 15){
            square.firstChild.firstChild.classList.add('black')
        }

        if ( i >= 48){
            square.firstChild.firstChild.classList.add('white')
        }
        
        gameboard.append(square)   
    })
}
createBoard();

const allSquares = document.querySelectorAll("#gameboard .square")
allSquares.forEach(square=>{
    square.addEventListener('dragstart', dragStart)
    square.addEventListener('dragover', dragOver)
    square.addEventListener('drop', dragDrop)
const server = http.createServer((req, res) => {
  res.writeHead(200, { 'content-type': 'text/html' })
  fs.createReadStream('index.html').pipe(res)
})

let startPositionId  
let draggedElement

function dragStart (e) {
    startPositionId = e.target.parentNode.getAttribute('square-id')
    draggedElement = e.target
}

function dragOver(e){
    e.preventDefault()
}

function dragDrop(e){
    e.stopPropagation()
    console.log(e.target)
    const taken = e.target.classList.contains('piece')
    // e.target.parentNode.append(draggedElement)
    // e.target.remove()
    // e.target.append(draggedElement)
    changePlayer() 
}
console.log('Server running at http://localhost:3000/')

function changePlayer(){
    if (playerGo === "black") {
        playerGo = "white"
        playerDisplay.textContent = 'white'
    }
 else {
    playerGo = "black"
    playerDisplay.textContent = 'black'   
    }
}
 
server.listen(process.env.PORT || 3000)

``` I don't understand why the file was not just automatically updated and what do I need to do to fix this?

My current app.js file looks like this and is what I thought I had uploaded to my github to replace the older app.js

const playerDisplay = document.querySelector("#player");
const infoDisplay = document.querySelector("#info-display");
const width = 8; 
let playerGo = 'black'
playerDisplay.textContent = 'black'

const startPieces = [
    rook, knight, bishop, queen, king, bishop, knight, rook,
    pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
    '', '', '', '', '', '', '', '',
    '', '', '', '', '', '', '', '',
    '', '', '', '', '', '', '', '',
    '', '', '', '', '', '', '', '',
    pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn,
    rook, knight, bishop, queen, king, bishop, knight, rook,
]

function createBoard(){
    startPieces.forEach((startPiece, i) => {
        const square = document.createElement('div')
        square.classList.add('square')
        square.innerHTML = startPiece
        square.firstChild?.setAttribute('draggable', true)
        square.setAttribute('square-id', i)
        //square.classList.add('beige')
        const row = Math.floor((63-i)/8) + 1
        if (row %2 === 0){
            square.classList.add(i % 2 === 0 ? "beige" : "brown")
        }
        else {
            square.classList.add(i % 2 === 0 ? "brown" : "beige")
        }
        if ( i <= 15){
            square.firstChild.firstChild.classList.add('black')
        }

        if ( i >= 48){
            square.firstChild.firstChild.classList.add('white')
        }
        
        gameboard.append(square)   
    })
}
createBoard();

const allSquares = document.querySelectorAll(".square")
allSquares.forEach(square=>{
    square.addEventListener('dragstart', dragStart)
    square.addEventListener('dragover', dragOver)
    square.addEventListener('drop', dragDrop)
})

let startPositionId  
let draggedElement

function dragStart (e) {
    startPositionId = e.target.parentNode.getAttribute('square-id')
    draggedElement = e.target
}

function dragOver(e){
    e.preventDefault()
}

function dragDrop(e){
    e.stopPropagation()
    console.log('e.target', e.target)
    const correctGo = draggedElement.firstChild.classList.contains(playerGo)
    const taken = e.target.classList.contains('piece')
    const opponentGo = playerGo === 'white' ? 'black' : 'white'
    const takenByOpponent = e.target.firstChild?.classList.contains(opponentGo)
    
    if (correctGo) {
        // //must check this first
        // if(takenByOpponent && valid){
        //     e.target.parentNode.append(draggedElement)
        //      e.target.remove()
        //      changePlayer()
        //      return
        // } 
        // then check this
        if (taken && !takenByOpponent) {
            infoDisplay.textContent = "you cannot go here!"
            setTimeout(() => infoDisplay.textContent = "", 2000)
            return
        } 
    }
    
   
   
    // e.target.append(draggedElement)
   
}

function changePlayer(){
    if (playerGo === "black") {
        reverseIds()
        playerGo = "white"
        playerDisplay.textContent = 'white'
    }
 else {
    revertIds()
    playerGo = "black"
    playerDisplay.textContent = 'black'   
    }
}
 
function reverseIds() {
    const allSquares = document.querySelectorAll(".square")
    allSquares.forEach((square, i) => 
    square.setAttribute('square-id', (width * width -1) - i))
}

function revertIds(){
    const allSquares = document.querySelectorAll(".square")
    allSquares.forEach((square, i) => square.setAttribute('square-id', i))
}```

maybe you should learn to use git, so you can make the commit locally and push to your repo to update. Manually uploading files is not how github is programmed to be used so it can not work exactly.

Also check that the file you are uploading manually is saved before you do that.