Onclick, the button moves down, why can that due to? - javascript

Whenever I click a button and the value is inputted, the values in the box goes down. I've tried changing some CSS but it doesn't work as I intend it to.
const game = (() => {
const createPlayer = (name, marker, turn) => {
return { name, marker, turn }
}
player1 = createPlayer('Player 1', "x", true)
player2 = createPlayer('Player 2', "o", false)
const gameBoard = () => {
var gameBoard = []
const movement = (e) => {
if (player1.turn === true && e.target.textContent === "") {
gameBoard[e.target.id] = player1.marker
e.target.textContent = player1.marker
player1.turn = false
} else if (player1.turn === false && e.target.textContent === "") {
gameBoard[e.target.id] = player2.marker
e.target.textContent = player2.marker
player1.turn = true
}
if (gameBoard["button-1"] === "x" && gameBoard["button-2"] === "x" && gameBoard["button-3"] === "x") {
alert("perfect")
} else if (gameBoard["button-4"] === "x" && gameBoard["button-5"] === "x" && gameBoard["button-6"] === "x") {
alert("you win")
} else if (gameBoard["button-7"] === "x" && gameBoard["button-8"] === "x" && gameBoard["button-9"] === "x") {
alert("you win")
} else if (gameBoard["button-1"] === "x" && gameBoard["button-4"] === "x" && gameBoard["button-7"] === "x") {
alert("you win")
} else if (gameBoard["button-2"] === "x" && gameBoard["button-5"] === "x" && gameBoard["button-8"] === "x") {
alert("you win")
} else if (gameBoard["button-3"] === "x" && gameBoard["button-6"] === "x" && gameBoard["button-9"] === "x") {
alert("you win")
} else if (gameBoard["button-1"] === "o" && gameBoard["button-2"] === "o" && gameBoard["button-3"] === "o") {
alert("perfect")
} else if (gameBoard["button-4"] === "o" && gameBoard["button-5"] === "o" && gameBoard["button-6"] === "o") {
alert("you win")
} else if (gameBoard["button-7"] === "o" && gameBoard["button-8"] === "o" && gameBoard["button-9"] === "o") {
alert("you win")
} else if (gameBoard["button-1"] === "o" && gameBoard["button-4"] === "o" && gameBoard["button-7"] === "o") {
alert("you win")
} else if (gameBoard["button-2"] === "o" && gameBoard["button-5"] === "o" && gameBoard["button-8"] === "o") {
alert("you win")
} else if (gameBoard["button-3"] === "o" && gameBoard["button-6"] === "o" && gameBoard["button-9"] === "o") {
alert("you win")
} else if (gameBoard["button-1"] === "o" && gameBoard["button-5"] === "o" && gameBoard["button-9"] === "o") {
alert("you win")
} else if (gameBoard["button-3"] === "o" && gameBoard["button-5"] === "o" && gameBoard["button-7"] === "o") {
alert("you win")
} else if (gameBoard["button-1"] === "x" && gameBoard["button-5"] === "x" && gameBoard["button-9"] === "x") {
alert("you win")
} else if (gameBoard["button-3"] === "x" && gameBoard["button-5"] === "x" && gameBoard["button-7"] === "x") {
alert("you win")
}
}
const board = document.querySelector('.item-board').addEventListener('click', movement)
}
gameBoard()
})
game()
.header {
background-color: red;
background-size: cover;
width: 100%;
height: 100%;
}
.item-board {
margin-left: 200px;
display: inline-block;
}
.TicTac {
background-size: cover;
width: 100%;
height: 100%;
}
.btn-1 {
width: 100px;
height: 100px;
border: 2px solid;
margin: -2px;
font-size: 4rem;
padding: 0px;
}
p {
font-size: 200px;
}
<header class="header">
<h1 class="TicTac">Tic-Tac-Toe</h1>
</header>
<div class="item-board">
<div class="item-board">
<button type="button" name="button" id="button-1" class="btn-1"></button>
<button type="button" name="button" id="button-2" class="btn-1"></button>
<button type="button" name="button" id="button-3" class="btn-1"></button>
</div>
<div class="item-board">
<button type="button" name="button" id="button-4" class="btn-1"></button>
<button type="button" name="button" id="button-5" class="btn-1"></button>
<button type="button" name="button" id="button-6" class="btn-1"></button>
</div>
<div class="item-board">
<button type="button" name="button" id="button-7" class="btn-1"></button>
<button type="button" name="button" id="button-8" class="btn-1"></button>
<button type="button" name="button" id="button-9" class="btn-1"></button>
</div>
</div>
I've tried changing some CSS but can't figure out how to make it so that it doesn't go down on each click.

Your .btn-1 styling is aligning the elements based on their text content, this can be solved by applying vertical-align: top; to that class.
Another small change that's worth making would be to change .item-board from inline-block to display: block, as that will prevent the width of the screen affecting whether the rows wrap.
const game = (() => {
const createPlayer = (name, marker, turn) => {
return { name, marker, turn }
}
player1 = createPlayer('Player 1', "x", true)
player2 = createPlayer('Player 2', "o", false)
const gameBoard = () => {
var gameBoard = []
const movement = (e) => {
if (player1.turn === true && e.target.textContent === "") {
gameBoard[e.target.id] = player1.marker
e.target.textContent = player1.marker
player1.turn = false
} else if (player1.turn === false && e.target.textContent === "") {
gameBoard[e.target.id] = player2.marker
e.target.textContent = player2.marker
player1.turn = true
}
if (gameBoard["button-1"] === "x" && gameBoard["button-2"] === "x" && gameBoard["button-3"] === "x") {
alert("perfect")
} else if (gameBoard["button-4"] === "x" && gameBoard["button-5"] === "x" && gameBoard["button-6"] === "x") {
alert("you win")
} else if (gameBoard["button-7"] === "x" && gameBoard["button-8"] === "x" && gameBoard["button-9"] === "x") {
alert("you win")
} else if (gameBoard["button-1"] === "x" && gameBoard["button-4"] === "x" && gameBoard["button-7"] === "x") {
alert("you win")
} else if (gameBoard["button-2"] === "x" && gameBoard["button-5"] === "x" && gameBoard["button-8"] === "x") {
alert("you win")
} else if (gameBoard["button-3"] === "x" && gameBoard["button-6"] === "x" && gameBoard["button-9"] === "x") {
alert("you win")
} else if (gameBoard["button-1"] === "o" && gameBoard["button-2"] === "o" && gameBoard["button-3"] === "o") {
alert("perfect")
} else if (gameBoard["button-4"] === "o" && gameBoard["button-5"] === "o" && gameBoard["button-6"] === "o") {
alert("you win")
} else if (gameBoard["button-7"] === "o" && gameBoard["button-8"] === "o" && gameBoard["button-9"] === "o") {
alert("you win")
} else if (gameBoard["button-1"] === "o" && gameBoard["button-4"] === "o" && gameBoard["button-7"] === "o") {
alert("you win")
} else if (gameBoard["button-2"] === "o" && gameBoard["button-5"] === "o" && gameBoard["button-8"] === "o") {
alert("you win")
} else if (gameBoard["button-3"] === "o" && gameBoard["button-6"] === "o" && gameBoard["button-9"] === "o") {
alert("you win")
} else if (gameBoard["button-1"] === "o" && gameBoard["button-5"] === "o" && gameBoard["button-9"] === "o") {
alert("you win")
} else if (gameBoard["button-3"] === "o" && gameBoard["button-5"] === "o" && gameBoard["button-7"] === "o") {
alert("you win")
} else if (gameBoard["button-1"] === "x" && gameBoard["button-5"] === "x" && gameBoard["button-9"] === "x") {
alert("you win")
} else if (gameBoard["button-3"] === "x" && gameBoard["button-5"] === "x" && gameBoard["button-7"] === "x") {
alert("you win")
}
}
const board = document.querySelector('.item-board').addEventListener('click', movement)
}
gameBoard()
})
game()
.header {
background-color: red;
background-size: cover;
width: 100%;
height: 100%;
}
.item-board {
margin-left: 50px;
display: block; /* This prevents the rows appearing on the same line on wide screens */
}
.TicTac {
background-size: cover;
width: 100%;
height: 100%;
}
.btn-1 {
width: 100px;
height: 100px;
border: 2px solid;
margin: -2px;
font-size: 4rem;
padding: 0px;
vertical-align: top; /* Top will fix the alignment issue when text content is added to the button */
}
p {
font-size: 200px;
}
<header class="header">
<h1 class="TicTac">Tic-Tac-Toe</h1>
</header>
<div class="item-board">
<div class="item-board">
<button type="button" name="button" id="button-1" class="btn-1"></button>
<button type="button" name="button" id="button-2" class="btn-1"></button>
<button type="button" name="button" id="button-3" class="btn-1"></button>
</div>
<div class="item-board">
<button type="button" name="button" id="button-4" class="btn-1"></button>
<button type="button" name="button" id="button-5" class="btn-1"></button>
<button type="button" name="button" id="button-6" class="btn-1"></button>
</div>
<div class="item-board">
<button type="button" name="button" id="button-7" class="btn-1"></button>
<button type="button" name="button" id="button-8" class="btn-1"></button>
<button type="button" name="button" id="button-9" class="btn-1"></button>
</div>
</div>

Try using a grid layout for your board.
I cleaned-up the CSS so that it is easier to follow. I also made the players an array and added a turn counter.
The board element is now passed to the function.
Cell lookup is easier when using indicies.
Cells are now regular <div> elements.
The cell dataset (attributes) holds the marker reference.
The cell occupied check is also easier now.
Cell clicks are delegated by the board.
Hopefully this is much easier to understand. I tried to keep the general structure of your functions.
const game = ((el) => {
const createPlayer = (name, marker) =>
({ name, marker });
let turn = 0;
const players = [
createPlayer('Player 1', 'X'),
createPlayer('Player 2', 'O')
];
const gameBoard = () => {
var gameBoard = [];
const getCell = index => el.querySelector(`.cell:nth-child(${index + 1})`);
const getCells = (...indicies) => indicies.map(getCell);
const allOccupied = (marker, ...indicies) =>
getCells(...indicies).every(cell => cell.dataset.marker === marker);
const checkWin = ({ marker }) =>
allOccupied(marker, 0, 1, 2) /* horiz / top */
|| allOccupied(marker, 3, 4, 5) /* horiz / middle */
|| allOccupied(marker, 5, 7, 8) /* horiz / bottom */
|| allOccupied(marker, 0, 3, 6) /* vert / left */
|| allOccupied(marker, 1, 4, 7) /* vert / middle */
|| allOccupied(marker, 2, 5, 8) /* vert / right */
|| allOccupied(marker, 0, 4, 8) /* diag / negative */
|| allOccupied(marker, 2, 4, 6); /* diag / positive */
const delagateClick = (e) => {
if (e.target.classList.contains('cell')) {
handleMovement(e.target);
}
};
const handleMovement = (cell) => {
const player = players[turn % players.length];
if (!cell.dataset.marker) {
cell.dataset.marker = player.marker;
cell.textContent = player.marker;
if (checkWin(player)) {
setTimeout(() => {
alert(`${player.name} ("${player.marker}") wins`);
}, 100);
}
turn++;
}
};
el.addEventListener('click', delagateClick);
}
gameBoard()
})
game(document.querySelector('.board'));
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
body {
display: flex;
flex-direction: column;
align-items: center;
font-family: Arial;
background: #000;
color: #EEE;
}
header {
display: flex;
justify-content: center;
align-items: center;
background-color: #C33;
background-size: cover;
width: 100%;
height: 4em;
}
header > div {
font-size: 2em;
font-weight: bold;
}
main {
display: flex;
flex: 1;
align-items: center;
justify-content: center;
background: #222;
width: 100%;
}
.board {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 0.25em;
border: thin solid grey;
background: #444;
padding: 0.25em;
}
.cell {
display: flex;
width: 2em;
height: 2em;
border: thin solid grey;
font-size: 2em;
align-items: center;
justify-content: center;
background: #666;
cursor: pointer;
}
.cell:not([data-marker]):hover {
background: #888;
}
.cell[data-marker] {
cursor: not-allowed;
}
<header>
<div>Tic-Tac-Toe</div>
</header>
<main>
<div class="board">
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
</div>
</main>

Related

How to center innerHTML in a button?

I have a very simple TicTacToe game that works perfectly with Firefox in Fedora but when I use a Chromium based browser or Windows the "X"s and "O"s are misplaced and the font not used.
var c=0
function a(b){
"X"!=document.getElementById(b).innerHTML&&"O"!=document.getElementById(b).innerHTML&&0==c?(document.getElementById(b).innerHTML="X",c=1):
"X"!=document.getElementById(b).innerHTML&&"O"!=document.getElementById(b).innerHTML&&1==c&&(document.getElementById(b).innerHTML="O",c=0)
z()
}
function r(b){for(c=0;8>=b;b++)document.getElementById(b).innerHTML=""}
function z(){
"X"==document.getElementById(0).innerHTML&&"X"==document.getElementById(1).innerHTML&&"X"==document.getElementById(2).innerHTML?x():
"X"==document.getElementById(3).innerHTML&&"X"==document.getElementById(4).innerHTML&&"X"==document.getElementById(5).innerHTML?x():
"X"==document.getElementById(6).innerHTML&&"X"==document.getElementById(7).innerHTML&&"X"==document.getElementById(8).innerHTML?x():
"X"==document.getElementById(0).innerHTML&&"X"==document.getElementById(3).innerHTML&&"X"==document.getElementById(6).innerHTML?x():
"X"==document.getElementById(1).innerHTML&&"X"==document.getElementById(4).innerHTML&&"X"==document.getElementById(7).innerHTML?x():
"X"==document.getElementById(2).innerHTML&&"X"==document.getElementById(5).innerHTML&&"X"==document.getElementById(8).innerHTML?x():
"X"==document.getElementById(0).innerHTML&&"X"==document.getElementById(4).innerHTML&&"X"==document.getElementById(8).innerHTML?x():
"X"==document.getElementById(2).innerHTML&&"X"==document.getElementById(4).innerHTML&&"X"==document.getElementById(6).innerHTML?x():
"O"==document.getElementById(0).innerHTML&&"O"==document.getElementById(1).innerHTML&&"O"==document.getElementById(2).innerHTML?o():
"O"==document.getElementById(3).innerHTML&&"O"==document.getElementById(4).innerHTML&&"O"==document.getElementById(5).innerHTML?o():
"O"==document.getElementById(6).innerHTML&&"O"==document.getElementById(7).innerHTML&&"O"==document.getElementById(8).innerHTML?o():
"O"==document.getElementById(0).innerHTML&&"O"==document.getElementById(3).innerHTML&&"O"==document.getElementById(6).innerHTML?o():
"O"==document.getElementById(1).innerHTML&&"O"==document.getElementById(4).innerHTML&&"O"==document.getElementById(7).innerHTML?o():
"O"==document.getElementById(2).innerHTML&&"O"==document.getElementById(5).innerHTML&&"O"==document.getElementById(8).innerHTML?o():
"O"==document.getElementById(0).innerHTML&&"O"==document.getElementById(4).innerHTML&&"O"==document.getElementById(8).innerHTML?o():
"O"==document.getElementById(2).innerHTML&&"O"==document.getElementById(4).innerHTML&&"O"==document.getElementById(6).innerHTML&&o()
}
function x(){alert("Ha guanyat X!");c=2}
function o(){alert("Ha guanyat O!");c=2}
body{background-color:#001c5a}
button{
cursor:pointer;
font-family:Tahoma;
font-weight:bolder;
font-size:xx-large;
}
#s{
cursor:default;
margin: 2%;
color:white
}
#q{
width:30rem;
display:flex;
flex-wrap:wrap;
border:solid #c1133d
}
#q button{
display:flex;
flex-direction:column;
width:10rem;
height:10rem;
padding-top:3.5rem;
background-color:#84C7D6;
color:#000;
border:solid #c1133d
}
#x {
width:30rem;
margin: 2%;
padding:2% 2%;
background-color:#c1133d;
color:white;
border:0;
border-radius:66px
}
<html>
<head>
<link rel="stylesheet" href="b.css">
<script src="c.js"></script>
<title>3 en ratlla</title>
</head>
<body>
<center>
<h1 id="s">A jugar!</h1>
<div id="q">
<button id="0" onclick="a(0)"></button>
<button id="1" onclick="a(1)"></button>
<button id="2" onclick="a(2)"></button>
<button id="3" onclick="a(3)"></button>
<button id="4" onclick="a(4)"></button>
<button id="5" onclick="a(5)"></button>
<button id="6" onclick="a(6)"></button>
<button id="7" onclick="a(7)"></button>
<button id="8" onclick="a(8)"></button>
</div>
<button id="x" onclick="r(0)">Tornar a començar</button>
</center>
</body>
</html>
I have tried different browsers and operating sistems, it should work but sometimes it does not. Idk why in Windows it does not use the font I want.
Browsers:
Firefox
Chromium
Google Chrome
Solutions (non working):
text-align
justify-content
vertical-align
Tried using display:flex and it worked for me.
var c=0
function a(b){
"X"!=document.getElementById(b).innerHTML&&"O"!=document.getElementById(b).innerHTML&&0==c?(document.getElementById(b).innerHTML="X",c=1):
"X"!=document.getElementById(b).innerHTML&&"O"!=document.getElementById(b).innerHTML&&1==c&&(document.getElementById(b).innerHTML="O",c=0)
z()
}
function r(b){for(c=0;8>=b;b++)document.getElementById(b).innerHTML=""}
function z(){
"X"==document.getElementById(0).innerHTML&&"X"==document.getElementById(1).innerHTML&&"X"==document.getElementById(2).innerHTML?x():
"X"==document.getElementById(3).innerHTML&&"X"==document.getElementById(4).innerHTML&&"X"==document.getElementById(5).innerHTML?x():
"X"==document.getElementById(6).innerHTML&&"X"==document.getElementById(7).innerHTML&&"X"==document.getElementById(8).innerHTML?x():
"X"==document.getElementById(0).innerHTML&&"X"==document.getElementById(3).innerHTML&&"X"==document.getElementById(6).innerHTML?x():
"X"==document.getElementById(1).innerHTML&&"X"==document.getElementById(4).innerHTML&&"X"==document.getElementById(7).innerHTML?x():
"X"==document.getElementById(2).innerHTML&&"X"==document.getElementById(5).innerHTML&&"X"==document.getElementById(8).innerHTML?x():
"X"==document.getElementById(0).innerHTML&&"X"==document.getElementById(4).innerHTML&&"X"==document.getElementById(8).innerHTML?x():
"X"==document.getElementById(2).innerHTML&&"X"==document.getElementById(4).innerHTML&&"X"==document.getElementById(6).innerHTML?x():
"O"==document.getElementById(0).innerHTML&&"O"==document.getElementById(1).innerHTML&&"O"==document.getElementById(2).innerHTML?o():
"O"==document.getElementById(3).innerHTML&&"O"==document.getElementById(4).innerHTML&&"O"==document.getElementById(5).innerHTML?o():
"O"==document.getElementById(6).innerHTML&&"O"==document.getElementById(7).innerHTML&&"O"==document.getElementById(8).innerHTML?o():
"O"==document.getElementById(0).innerHTML&&"O"==document.getElementById(3).innerHTML&&"O"==document.getElementById(6).innerHTML?o():
"O"==document.getElementById(1).innerHTML&&"O"==document.getElementById(4).innerHTML&&"O"==document.getElementById(7).innerHTML?o():
"O"==document.getElementById(2).innerHTML&&"O"==document.getElementById(5).innerHTML&&"O"==document.getElementById(8).innerHTML?o():
"O"==document.getElementById(0).innerHTML&&"O"==document.getElementById(4).innerHTML&&"O"==document.getElementById(8).innerHTML?o():
"O"==document.getElementById(2).innerHTML&&"O"==document.getElementById(4).innerHTML&&"O"==document.getElementById(6).innerHTML&&o()
}
function x(){alert("Ha guanyat X!");c=2}
function o(){alert("Ha guanyat O!");c=2}
body{background-color:#001c5a}
button{
cursor:pointer;
font-family:Tahoma;
font-weight:bolder;
font-size:xx-large;
}
#s{
cursor:default;
margin: 2%;
color:white
}
#q{
width:30rem;
display:flex;
flex-wrap:wrap;
border:solid #c1133d
}
#q button{
display:flex;
padding: 0;
justify-content: center;
align-content: space-around;
align-items: center;
width:10rem;
height:10rem;
background-color:#84C7D6;
color:#000;
border:solid #c1133d
}
#x {
width:30rem;
margin: 2%;
padding:2% 2%;
background-color:#c1133d;
color:white;
border:0;
border-radius:66px
}
<html>
<head>
<link rel="stylesheet" href="b.css">
<script src="c.js"></script>
<title>3 en ratlla</title>
</head>
<body>
<center>
<h1 id="s">A jugar!</h1>
<div id="q">
<button id="0" onclick="a(0)"></button>
<button id="1" onclick="a(1)"></button>
<button id="2" onclick="a(2)"></button>
<button id="3" onclick="a(3)"></button>
<button id="4" onclick="a(4)"></button>
<button id="5" onclick="a(5)"></button>
<button id="6" onclick="a(6)"></button>
<button id="7" onclick="a(7)"></button>
<button id="8" onclick="a(8)"></button>
</div>
<button id="x" onclick="r(0)">Tornar a començar</button>
</center>
</body>
</html>
Give the button flexbox style:
button {
display: flex;
align-items: center;
justify-content: center;
}
And remove the top padding.
var c = 0
function a(b) {
var el = document.getElementById(b);
"X" != el.innerHTML && "O" != el.innerHTML && 0 == c ? (el.innerHTML = "X", c = 1) :
"X" != el.innerHTML && "O" != el.innerHTML && 1 == c && (el.innerHTML = "O", c = 0)
z()
}
function r(b) {
for (c = 0; 8 >= b; b++) document.getElementById(b).innerHTML = ""
}
function z() {
"X" == document.getElementById(0).innerHTML && "X" == document.getElementById(1).innerHTML && "X" == document.getElementById(2).innerHTML ? x() :
"X" == document.getElementById(3).innerHTML && "X" == document.getElementById(4).innerHTML && "X" == document.getElementById(5).innerHTML ? x() :
"X" == document.getElementById(6).innerHTML && "X" == document.getElementById(7).innerHTML && "X" == document.getElementById(8).innerHTML ? x() :
"X" == document.getElementById(0).innerHTML && "X" == document.getElementById(3).innerHTML && "X" == document.getElementById(6).innerHTML ? x() :
"X" == document.getElementById(1).innerHTML && "X" == document.getElementById(4).innerHTML && "X" == document.getElementById(7).innerHTML ? x() :
"X" == document.getElementById(2).innerHTML && "X" == document.getElementById(5).innerHTML && "X" == document.getElementById(8).innerHTML ? x() :
"X" == document.getElementById(0).innerHTML && "X" == document.getElementById(4).innerHTML && "X" == document.getElementById(8).innerHTML ? x() :
"X" == document.getElementById(2).innerHTML && "X" == document.getElementById(4).innerHTML && "X" == document.getElementById(6).innerHTML ? x() :
"O" == document.getElementById(0).innerHTML && "O" == document.getElementById(1).innerHTML && "O" == document.getElementById(2).innerHTML ? o() :
"O" == document.getElementById(3).innerHTML && "O" == document.getElementById(4).innerHTML && "O" == document.getElementById(5).innerHTML ? o() :
"O" == document.getElementById(6).innerHTML && "O" == document.getElementById(7).innerHTML && "O" == document.getElementById(8).innerHTML ? o() :
"O" == document.getElementById(0).innerHTML && "O" == document.getElementById(3).innerHTML && "O" == document.getElementById(6).innerHTML ? o() :
"O" == document.getElementById(1).innerHTML && "O" == document.getElementById(4).innerHTML && "O" == document.getElementById(7).innerHTML ? o() :
"O" == document.getElementById(2).innerHTML && "O" == document.getElementById(5).innerHTML && "O" == document.getElementById(8).innerHTML ? o() :
"O" == document.getElementById(0).innerHTML && "O" == document.getElementById(4).innerHTML && "O" == document.getElementById(8).innerHTML ? o() :
"O" == document.getElementById(2).innerHTML && "O" == document.getElementById(4).innerHTML && "O" == document.getElementById(6).innerHTML && o()
}
function x() {
alert("Ha guanyat X!");
c = 2
}
function o() {
alert("Ha guanyat O!");
c = 2
}
body {
background-color: #001c5a
}
button {
display: flex; /* add */
align-items: center; /* add */
justify-content: center; /* add */
cursor: pointer;
font-family: Tahoma;
font-weight: bolder;
font-size: xx-large;
}
#s {
cursor: default;
margin: 2%;
color: white
}
#q {
width: 30rem;
display: flex;
flex-wrap: wrap;
border: solid #c1133d
}
#q button {
display: flex;
flex-direction: column;
width: 10rem;
height: 10rem;
/* padding-top: 3.5rem; -- remove */
background-color: #84C7D6;
color: #000;
border: solid #c1133d
}
#x {
width: 30rem;
margin: 2%;
padding: 2% 2%;
background-color: #c1133d;
color: white;
border: 0;
border-radius: 66px
}
<html>
<head>
<link rel="stylesheet" href="b.css">
<script src="c.js"></script>
<title>3 en ratlla</title>
</head>
<body>
<center>
<h1 id="s">A jugar!</h1>
<div id="q">
<button id="0" onclick="a(0)"></button>
<button id="1" onclick="a(1)"></button>
<button id="2" onclick="a(2)"></button>
<button id="3" onclick="a(3)"></button>
<button id="4" onclick="a(4)"></button>
<button id="5" onclick="a(5)"></button>
<button id="6" onclick="a(6)"></button>
<button id="7" onclick="a(7)"></button>
<button id="8" onclick="a(8)"></button>
</div>
<button id="x" onclick="r(0)">Tornar a començar</button>
</center>
</body>
</html>

Why is my rock paper scissors not working on the first click, the game works fine but the first click does nothing

As explained in the title, for some reason the first time you click it doesn't work but the second click goes through and the game works fine onwards, can anyone explain why? can't figure it out with my noob brain:
The game logic works perfectly fine, I know I've gone about it in a roundabout way but forgive me I'm still a noob and plan to keep iterating on this to make it more efficient.
Am I applying the styling to display the results in the wrong place or can you point me to why its not instantly starting the game?
const pickIcon = document.getElementsByClassName('icons');
const pickWord = document.getElementsByClassName('word-choice');
const rockWord = document.getElementById('rock-word');
const paperWord = document.getElementById('paper-word');
const scissorsWord = document.getElementById('scissors-word');
// const resultContainer = document.getElementById('result');
let picksDisplay = document.getElementById('picks');
let resultDisplay = document.getElementById('winner-result');
let resultShow = document.getElementById('result-game');
let userPickIcon = ''
let userPick = ''
let compPick = ''
function playGame() {
//player pick
for (let i = 0; i < pickIcon.length; i++) {
pickIcon[i].addEventListener('click', function() {
document.getElementById('result').style.display = 'block';
if (pickIcon[i] === pickIcon[0] || pickIcon[i] === pickIcon[3]) {
userPickIcon = 'rock'
picksDisplay.innerText = `Player picked ${userPickIcon}`
} else if (pickIcon[i] === pickIcon[1] || pickIcon[i] === pickIcon[4]) {
userPickIcon = 'paper'
picksDisplay.innerText = `Player picked ${userPickIcon}`
} else if (pickIcon[i] === pickIcon[2] || pickIcon[i] === pickIcon[5]) {
userPickIcon = 'scissors'
picksDisplay.innerText = `Player picked ${userPickIcon}`
}
})
}
// computer randomised pick
let computerChoice = Math.floor(Math.random() * 3);
if (computerChoice === 0) {
compPick = 'rock'
resultDisplay.innerText = `Computer picked ${compPick}`
} else if (computerChoice === 1) {
compPick = 'paper'
resultDisplay.innerText = `Computer picked ${compPick}`
} else if (computerChoice === 2) {
compPick = 'scissors'
resultDisplay.innerText = `Computer picked ${compPick}`
}
//gamelogic
if (userPickIcon === compPick) {
resultShow.innerText = `The game is a tie!!!`
} else {
if (userPickIcon === 'rock') {
if (compPick === 'paper') {
resultShow.innerText = `Computer is the winner, Sorry :(`
} else {
resultShow.innerText = `The Player is the winner, Congratulations!!`
}
};
if (userPickIcon === 'paper') {
if (compPick === 'scissors') {
resultShow.innerText = `Computer is the winner, Sorry :(`
} else {
resultShow.innerText = `The Player is the winner, Congratulations!!`
}
};
if (userPickIcon === 'scissors') {
if (compPick === 'rock') {
resultShow.innerText = `Computer is the winner, Sorry :(`
} else {
resultShow.innerText = `The Player is the winner, Congratulations!!`
}
}
}
}
document.addEventListener('click', playGame);
#import url('https://fonts.googleapis.com/css2?family=Montserrat:wght#400;500&family=Roboto+Mono&display=swap');
body {
background-color: #16213E;
font-family: 'Montserrat', sans-serif;
text-align: center;
}
.container {
background-color: #fff;
margin: 40px auto;
width: 500px;
color: #16213E;
}
.icons-div {
display: flex;
align-items: center;
justify-content: center;
}
i {
padding: 25px;
font-size: 70px;
color: #277BC0;
}
i:hover {
color: #1CD6CE;
cursor: pointer;
}
.word-choice:hover {
color: #1CD6CE;
cursor: pointer;
}
.title-div {
background-color: #277BC0;
padding: 10px 0;
color: #fff;
}
.results {
background-color: #fff;
width: 500px;
margin: 40px auto;
height: 200px;
display: none;
}
.result-items {
padding-top: 20px;
color: #16213E;
}
#result-game {
color: #495C83;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css" integrity="sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE+4aHK8yyUHUSCcJHgXloTyT2A==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>
<div class="container">
<div class="title-div">
<h2>Rock, Paper, Scissors</h2>
</div>
<div class="choices-title">
<h2>Make your choice</h2>
</div>
<div class="icons-div">
<table>
<tr>
<td><i class="fa-solid fa-hand-back-fist icons" id="rock-btn"></i></td>
<td><i class="fa-solid fa-hand icons" id="paper-btn"></i></td>
<td><i class="fa-solid fa-hand-scissors icons" id="scissors-btn"></i></td>
</tr>
<tr>
<td>
<h3 id="rock-word" class="word-choice icons">Rock</h3>
</td>
<td>
<h3 id="paper-word" class="word-choice icons">Paper</h3>
</td>
<td>
<h3 id="scissors-word" class="word-choice icons">Scissors</h3>
</td>
</tr>
</table>
</div>
</div>
<div class="results" id="result">
<div class="result-items">
<h3 id="picks"></h3>
<h3 id="winner-result"></h3>
<h2 id="result-game"></h2>
</div>
</div>
You added an eventListener to the whole document: document.addEventListener('click', playGame);
Which then calls the function playGame if anything is clicked. playGame function adds the eventListeners to your rock, paper and scissors only after you made your first click that called playGame.
As I stated already in the comments, there are a lot of issues. I not going to fix every issue such as semantics and accessibility issues as this would blow the proportion of an answer (take it as a hint to read into it and work on it in the future).
You had a text and an icon that could be clicked. This means while you still have only 3 choices to make you had 6 elements that you could click on. This overcomplicated the necessary logic. In other words, you had twice as many elements to check than necessary. I change it now that the eventListener listen to the container that contains an icon and the text.
You selected all the elements to check for the eventListener by using getElementsByClassName. This unfortunately returns an HTML Collection Object. As such you had to iterate through that object with a for-loop. This is highly inefficient and overcomplicated the issue as well. The smart and clean solution is to use querySelectorAll which will return a Node-List. The NodeList can be iterated with forEach which works faster and is shorter than a for-loop.
You nested a lot of if/else-statements. This is inefficient which a switch-statement and/or a ternary conditional operator can fix.
Now to the actual issue:
You have the entire logic running in a function. The eventListener is inside the function. So you have to click in your document first to run the function that then will start listing to the click events of the choices. That's why you need the extra click at the start.
If you programmed clean as described above you have the EventListener at the front and start the function when one of the choices is clicked on. That's what I meant in the comments, if you fix your major issues with your script performance-wise, the actual issue will resolve itself.
document.querySelectorAll('button').forEach(el =>
el.addEventListener('click', function(e) {
let playerChoice = e.currentTarget.id;
let userPick = '';
let computerPick = '';
// Get User Pick
switch (playerChoice) {
case 'rock-btn':
userPick = 'Rock';
break;
case 'paper-btn':
userPick = 'Paper';
break;
case 'scissors-btn':
userPick = 'Scissors';
break;
};
document.querySelector('#picks').textContent = `Player picked ${userPick}`;
// computer randomised pick
let computerChoice = Math.floor(Math.random() * 3);
switch (computerChoice) {
case 0:
computerPick = 'Rock';
break;
case 1:
computerPick = 'Paper';
break;
case 2:
computerPick = 'Scissors';
break;
};
document.querySelector('#winner-result').textContent = `Computer picked ${computerPick}`;
// game logic to check who wins;
let result = '';
if (userPick === computerPick) {
result = 'draw';
} else {
switch (userPick) {
case 'Rock':
result = (computerPick === 'Scissors') ? 'win' : 'lose';
break;
case 'Paper':
result = (computerPick === 'Rock') ? 'win' : 'lose';
break;
case 'Scissors':
result = (computerPick === 'Paper') ? 'win' : 'lose';
break;
};
};
// output for winner
let resultText = '';
switch (result) {
case 'draw':
resultText = 'The game is a tie!!!';
break;
case 'win':
resultText = 'The Player is the winner, Congratulations!!';
break;
case 'lose':
resultText = 'The Computer is the winner, Sorry :(';
break;
};
document.querySelector('#result-game').textContent = resultText;
// makes the result box visible
document.querySelector('#result').classList.remove('d-none');
})
)
#import url('https://fonts.googleapis.com/css2?family=Montserrat:wght#400;500&family=Roboto+Mono&display=swap');
body {
background-color: #16213E;
font-family: 'Montserrat', sans-serif;
text-align: center;
}
.container {
background-color: #fff;
margin: 40px auto;
width: 500px;
color: #16213E;
}
.icons-div {
display: flex;
align-items: center;
justify-content: center;
}
i {
padding: 25px;
font-size: 70px;
color: #277BC0;
}
button {
border: none;
background: transparent;
}
.icons-div > button:hover,
.icons-div > button:hover i,
.icons-div > button:hover h3 {
color: #1CD6CE;
cursor: pointer;
}
.title-div {
background-color: #277BC0;
padding: 10px 0;
color: #fff;
}
.results {
background-color: #fff;
width: 500px;
margin: 40px auto;
height: 200px;
}
.result-items {
padding-top: 20px;
color: #16213E;
}
.d-none {
display: none;
}
#result-game {
color: #495C83;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css" integrity="sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE+4aHK8yyUHUSCcJHgXloTyT2A==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>
<div class="container">
<div class="title-div">
<h2>Rock, Paper, Scissors</h2>
</div>
<div class="choices-title">
<h2>Make your choice</h2>
</div>
<div class="icons-div">
<button id="rock-btn">
<i class="fa-solid fa-hand-back-fist icons"></i>
<h3 class="word-choice icons">Rock</h3>
</button>
<button id="paper-btn">
<i class="fa-solid fa-hand icons"></i>
<h3 class="word-choice icons">Paper</h3>
</button>
<button id="scissors-btn">
<i class="fa-solid fa-hand-scissors icons"></i>
<h3 class="word-choice icons">Scissors</h3>
</button>
</div>
</div>
<div class="results d-none" id="result">
<div class="result-items">
<h3 id="picks"></h3>
<h3 id="winner-result"></h3>
<h2 id="result-game"></h2>
</div>
</div>

How to get keyboard/key selection to work in JavaScript

I am trying to build a simple sound machine with various sounds only using JavaScript, specifically, Zelda Ocarina of Time sounds. Yes, I know it's basic stuff, but I am still learning and can't for the life of me figure this out.
Now, I can get the left and right arrow keys to cycle through the choices, but when I use the keys: A,S,D,F,G, or H I can't get them to make a selection. No matter how many avenues I have tried.
Any help, tips, pointers, or ANYTHING constructive would be appreciated.
Sound Machine in browser
CODE:
const regions = Array.from(document.querySelectorAll('section[role="region"]'));
const keys = Array.from(document.querySelectorAll('#keys button'))
const keyTypes = keys.map(op => op.innerHTML);
const moveFocus = (region, item) => {
region[item].focus();
}
const handleArrowEvent = (event, items, currentRegion) => {
let currentItem =0;
if(
event.code === 'ArrowLeft' ||
event.code === 'ArrowRight' ||
event.code === 'KeyA' ||
event.code === 'KeyS' ||
event.code === 'KeyD' ||
event.code === 'KeyF' ||
event.code === 'KeyG' ||
event.code === 'KeyH'
) {
event.preventDefault();
event.stopPropagation();
console.log(event.target);
const regionItems = Array.from(currentRegion.children);
regionItems.forEach(child => {
items.push(child)
})
currentItem = items.indexOf(event.target);
const lastItem = items.length - 1;
const isFirst = currentItem === 0;
const isLast = currentItem === lastItem;
if(event.code === 'ArrowRight') {
currentItem = isLast ? 0 : currentItem + 1;
} else if (event.code === 'ArrowLeft') {
currentItem = isFirst ? lastItem : currentItem - 1;
}
moveFocus(regionItems, currentItem)
}
}
const handleClick = event => {
registerInput(event.target.innerHTML)
}
const handleKeyEvent = event => {
const items = [];
const currentRegion = event.target.closest('section[role="region"]')
if (
event.code === 'ArrowLeft' ||
event.code === 'ArrowRight' ||
event.code === 'KeyA' ||
event.code === 'KeyS' ||
event.code === 'KeyD' ||
event.code === 'KeyF' ||
event.code === 'KeyG' ||
event.code === 'KeyH'
) { handleArrowEvent(event, items, currentRegion) }
}
const registerInput = input => {
console.log(input)
}
#import url('https://fonts.googleapis.com/css2?family=Bangers&family=Heebo:wght#300&family=Press+Start+2P&display=swap');
html {
font-size: 10px;
background-image: url(../assets/img/lofz_ocTime.jpg);
background-size: cover;
}
body , html {
margin: 0;
padding: 0;
font-family: 'Bangers', cursive;
font-size: 12px;
}
#keys {
display: flex;
flex: 1;
min-height: 80vh;
align-items: center;
justify-content: center;
}
button {
border: .4rem solid rgb(255, 5, 5);
border-radius: .5rem;
margin: 1rem;
font-size: 1.5rem;
padding: 1rem .5rem;
transition: all 0.07s ease;
width: 10rem;
text-align: center;
color: rgb(31, 240, 3);
background: rgba(8, 7, 94, 0.753);
font-weight: bold;
text-shadow: 0 0 .5rem black;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./css/stylesheet.css">
<link rel="stylesheet" href="./css/normalize.css">
<title>Zelda: Ocarina of Time Sounds</title>
</head>
<body>
<section id="keys" aria-label="Zelda Sounds" role="region">
<button data-key="65" class="sound" class="key" aria-label="Key A">A<aside>Hey! Over Here!</aside></button>
<button data-key="83" class="sound" class="key" aria-label="Key S">S<aside>Link, Listen!</aside></button>
<button data-key="68" class="sound" class="key" aria-label="Key D">D<aside>Gold Skulltula</aside></button>
<button data-key="70" class="sound" class="key" aria-label="Key F">F<aside>Item Found!</aside></button>
<button data-key="71" class="sound" class="key" aria-label="Key G">G<aside>Silver Rupee</aside></button>
<button data-key="72" class="sound" class="key" aria-label="Key H">H<aside>Found a Heart!</aside></button>
</section>
<script src="js/main.js" type="module" defer></script>
</body>
</html>
you should try listening to keyboard input using 'keydown' event
document.addEventListener('keydown', function(e) {
if(e.code == "KeyA") {
console.log('A was pressed');
}
});
You can find the code for the key you want to listen using this website with the event.code value :
https://www.toptal.com/developers/keycode
Hope it helps !

&& in function not working

var pet = $("structureValue").val() == "Pet";
var Color = $("button").on("click",function(){
var color =$("#color");
var roof = $("#structureValue").val() == "Roof";
var building =$("#structureValue").val() == "Building";
var colorId=$(color).val();
if(colorId == "a" && roof){
$("#build").css("color", "grey")
}else if(colorId == "b" && roof){
$("#build").css("color", "green")
}else if(colorId == "c" && roof){
$("#build").css("color", "orange")
}else if(colorId == "d" && roof){
$("#build").css("color", "yellow")
}else if(colorId == "a" && building){
$("#building").css("background", "grey")
}else if(colorId == "b" && building){
$("#building").css("background", "green")
}else if(colorId == "c" && building){
$("#building").css("background", "orange")
}else if(colorId == "d" && building){
$("#building").css("background", "yellow")
}
});
/*--------------------Function------------------*/
$("#structureValue ").on("click",function(){
$("#structureValue").change(function(){
var val = $(this).val();
if(val == "Environment"){
$("#color").html("<option value='a'>Mountain</option><option value='b'>Lakeside</option><option value='c'>Beach</option><option value='d'>Island</option>");
}else if(val == "Pet"){
$("#color").html("<option value='a'>Squire</option><option value='b'>Chinchilla</option><option value='c'>Dinosaur</option><option value='d'>Dog</option>");
}else if (val == "Roof","Building"){
$("#color").html("<option value='a'>Gray</option><option value='b'>Green</option><option value='c'>Orange</option><option value='d'>Yellow</option>")}
});
});
$("#firstButton").on("click", function(){
var color =$("#color");
var colorId=$(color).val();
if($("#structureValue").val() == "Roof" ){
$("#build").css({"width":"0",
"height":"0","border-left":" 250px solid transparent","border-right":" 250px solid transparent",
"border-bottom":" 350px solid ","background":"none", Color });
}else if($("#structureValue").val() == "Building"){
$("#building").css({"width":"500px",
"height":"300px",Color })
}else if($("#structureValue").val() == "Environment" && colorId == "a"){
$("body").css({"background":"url('https://tpwd.texas.gov/state-parks/franklin-mountains/gallery/franklin-mnt_panorama1.jpg')no-repeat center center fixed",
"-webkit-background-size": "cover","-moz-background-size":"cover","-o-background-size": "cover","background-size":"cover","background-size":"100% 100%"});
}else if($("#structureValue").val() == "Environment" && colorId == "b"){
$("body").css({"background":"url('https://openclipart.org/image/2400px/svg_to_png/218873/Autumn-By-The-Lake.png')no-repeat center center fixed",
"-webkit-background-size": "cover","-moz-background-size":"cover","-o-background-size": "cover","background-size":"cover","background-size":"100% 100%"});
}else if($("#structureValue").val() == "Environment" && colorId == "c"){
$("body").css({"background":"url('http://travel.home.sndimg.com/content/dam/images/travel/fullset/2014/12/3/top-10-caribbean-beaches-eagle-beach-aruba.jpg.rend.hgtvcom.966.725.suffix/1491584555480.jpeg')no-repeat center center fixed",
"-webkit-background-size": "cover","-moz-background-size":"cover","-o-background-size": "cover","background-size":"cover","background-size":"100% 100%"});
}else if($("#structureValue").val() == "Environment" && colorId == "d"){
$("body").css({"background":"url('http://www.jeremyrobinsononline.com/wp-content/uploads/2013/05/White_Island_New_Zealand.jpg')no-repeat center center fixed",
"-webkit-background-size": "cover","-moz-background-size":"cover","-o-background-size": "cover","background-size":"cover","background-size":"100% 100%"});
}else if($("#structureValue").val() == "Pet" && colorId == "a"){
$("#pet").empty().append("<img class='secert' src='https://media.giphy.com/media/eGOorb2NowXny/giphy.gif'></img>");
}else if($("#structureValue").val() == "Pet" && colorId == "b"){
$("#pet").empty().append("<img class='secert' src='https://assets.horsenation.com/wp-content/uploads/2013/09/1379338067174322.gif'></img>");
}else if($("#structureValue").val() == "Pet" && colorId == "c"){
$("#pet").empty().append("<img class='secert' src='https://i0.wp.com/media.giphy.com/media/TfFbA8xkrIymk/giphy.gif?resize=500%2C281&ssl=1'></img>");
}else if($("#structureValue").val() == "Pet" && colorId == "d"){
$("#pet").empty().append("<img class='secert' src='http://s3.amazonaws.com/barkpost-assets/50+GIFs/17.gif'></img>");
}
});
$("#firstButton").click(function(){
if($("#structureValue").val() == "Building" && "Environment" && "Roof" && "Pet" ){
$("#suprise").css("visibility","visible");
}else{
console.log("wrong")
}
});
$("#suprise").click(function(){
$("#glide").addClass("glide");
setTimeout(function(){ $(".secert").css("visibility","visible");
}, 4500);
setTimeout(function(){
location.reload();
}, 8500);
})
body{background-color: green;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
background-size: 100% 100%
}
img{
max-width: 100%;
height: 300px;
}
#wrapper{
width: 100%;
text-align: center;
}
#build,#building,#doors,#windows{
margin: 0 auto;
}
.cf:before,
.cf:after {
content: " ";
display: table;
}
.cf:after {
clear: both;
}
.glide{
animation-name:glide;
animation-duration:8.5s;
animation-iteration-count: 1;
animation-direction:normal;
position: absolute;
}
#-webkit-keyframes glide {
0% { left:0px; top:0px;}
15% { left:0; top:50%;}
25% {left:80%; top:50%;}
35% {left:80%; top:0;}
40% { left:35%; top:0%;}
75% { left:35%; top:15%;}
100% { left:35%; top:15%;}
}
#suprise{
visibility:hidden;
margin-top: 30px;
}
.secert{
visibility: hidden;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="build a house.css">
<title></title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
</head>
<body class="cf">
<div id="wrapper">
<h1>What animal is in your house?</h1>
Create a home vision
<select id="structureValue">
<option value="Roof" name="structure">Roof</option>
<option value="Building" name="structure">Building</option>
<option value="Environment" name="structure">Environment</option>
<option value="Pet" name="structure">Pet</option>
</select>
Choose the details
<select id="color">
<option value="a">Gray</option>
<option value="b">Green</option>
<option value="c">Orange</option>
<option value="d">Yellow</option>
</select>
<button id="firstButton">Click Me</button>
<br>
<button id="suprise">What's in my house</button>
<div id="glide">
<div id="build">
</div>
<div id="building">
<div id="pet"></div>
</div>
</div>
<script type="text/javascript" src="build a house.js"></script>
</body>
</html>
My function isn't running through all the && before running. As of now when I click:
building green then click the function makes my surprise button visible. I want the function to have to click through all the options first not just the building value. Then allow my surprise button to become visible.
I want it to run as so:
Roof green(or other option) then click
Building green(or other option) then click
Location green(or other option) then click
Pet green(or other option) then click
After all has been completed, have the surprise button visible:
The function before last is the function I'm having issues with.
It starts as $("#firstButton").click(function()
var pet = $("structureValue").val() == "Pet";
var Color = $("button").on("click", function() {
var color = $("#color");
var roof = $("#structureValue").val() == "Roof";
var building = $("#structureValue").val() == "Building";
var colorId = $(color).val();
if (colorId == "a" && roof) {
$("#build").css("color", "grey")
} else if (colorId == "b" && roof) {
$("#build").css("color", "green")
} else if (colorId == "c" && roof) {
$("#build").css("color", "orange")
} else if (colorId == "d" && roof) {
$("#build").css("color", "yellow")
} else if (colorId == "a" && building) {
$("#building").css("background", "grey")
} else if (colorId == "b" && building) {
$("#building").css("background", "green")
} else if (colorId == "c" && building) {
$("#building").css("background", "orange")
} else if (colorId == "d" && building) {
$("#building").css("background", "yellow")
}
});
/*--------------------Function------------------*/
$("#structureValue ").on("click", function() {
$("#structureValue").change(function() {
var val = $(this).val();
if (val == "Environment") {
$("#color").html("<option value='a'>Mountain</option><option value='b'>Lakeside</option><option value='c'>Beach</option><option value='d'>Island</option>");
} else if (val == "Pet") {
$("#color").html("<option value='a'>Squire</option><option value='b'>Chinchilla</option><option value='c'>Dinosaur</option><option value='d'>Dog</option>");
} else if (val == "Roof", "Building") {
$("#color").html("<option value='a'>Gray</option><option value='b'>Green</option><option value='c'>Orange</option><option value='d'>Yellow</option>")
}
});
});
$("#firstButton").on("click", function() {
var color = $("#color");
var colorId = $(color).val();
if ($("#structureValue").val() == "Roof") {
$("#build").css({
"width": "0",
"height": "0",
"border-left": " 250px solid transparent",
"border-right": " 250px solid transparent",
"border-bottom": " 350px solid ",
"background": "none",
Color
});
} else if ($("#structureValue").val() == "Building") {
$("#building").css({
"width": "500px",
"height": "300px",
Color
})
} else if ($("#structureValue").val() == "Environment" && colorId == "a") {
$("body").css({
"background": "url('https://tpwd.texas.gov/state-parks/franklin-mountains/gallery/franklin-mnt_panorama1.jpg')no-repeat center center fixed",
"-webkit-background-size": "cover",
"-moz-background-size": "cover",
"-o-background-size": "cover",
"background-size": "cover",
"background-size": "100% 100%"
});
} else if ($("#structureValue").val() == "Environment" && colorId == "b") {
$("body").css({
"background": "url('https://openclipart.org/image/2400px/svg_to_png/218873/Autumn-By-The-Lake.png')no-repeat center center fixed",
"-webkit-background-size": "cover",
"-moz-background-size": "cover",
"-o-background-size": "cover",
"background-size": "cover",
"background-size": "100% 100%"
});
} else if ($("#structureValue").val() == "Environment" && colorId == "c") {
$("body").css({
"background": "url('http://travel.home.sndimg.com/content/dam/images/travel/fullset/2014/12/3/top-10-caribbean-beaches-eagle-beach-aruba.jpg.rend.hgtvcom.966.725.suffix/1491584555480.jpeg')no-repeat center center fixed",
"-webkit-background-size": "cover",
"-moz-background-size": "cover",
"-o-background-size": "cover",
"background-size": "cover",
"background-size": "100% 100%"
});
} else if ($("#structureValue").val() == "Environment" && colorId == "d") {
$("body").css({
"background": "url('http://www.jeremyrobinsononline.com/wp-content/uploads/2013/05/White_Island_New_Zealand.jpg')no-repeat center center fixed",
"-webkit-background-size": "cover",
"-moz-background-size": "cover",
"-o-background-size": "cover",
"background-size": "cover",
"background-size": "100% 100%"
});
} else if ($("#structureValue").val() == "Pet" && colorId == "a") {
$("#pet").empty().append("<img class='secert' src='https://media.giphy.com/media/eGOorb2NowXny/giphy.gif'></img>");
} else if ($("#structureValue").val() == "Pet" && colorId == "b") {
$("#pet").empty().append("<img class='secert' src='https://assets.horsenation.com/wp-content/uploads/2013/09/1379338067174322.gif'></img>");
} else if ($("#structureValue").val() == "Pet" && colorId == "c") {
$("#pet").empty().append("<img class='secert' src='https://i0.wp.com/media.giphy.com/media/TfFbA8xkrIymk/giphy.gif?resize=500%2C281&ssl=1'></img>");
} else if ($("#structureValue").val() == "Pet" && colorId == "d") {
$("#pet").empty().append("<img class='secert' src='http://s3.amazonaws.com/barkpost-assets/50+GIFs/17.gif'></img>");
}
});
$("#firstButton").click(function() {
if ($("#structureValue").val() == "Building" && $("#structureValue").val() == "Environment" && "Roof" && "Pet") {
$("#suprise").css("visibility", "visible");
} else {
console.log("wrong")
}
});
$("#suprise").click(function() {
$("#glide").addClass("glide");
setTimeout(function() {
$(".secert").css("visibility", "visible");
}, 4500);
setTimeout(function() {
location.reload();
}, 8500);
})
body {
background-color: green;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
background-size: 100% 100%
}
img {
max-width: 100%;
height: 300px;
}
#wrapper {
width: 100%;
text-align: center;
}
#build,
#building,
#doors,
#windows {
margin: 0 auto;
}
.cf:before,
.cf:after {
content: " ";
display: table;
}
.cf:after {
clear: both;
}
.glide {
animation-name: glide;
animation-duration: 8.5s;
animation-iteration-count: 1;
animation-direction: normal;
position: absolute;
}
#-webkit-keyframes glide {
0% {
left: 0px;
top: 0px;
}
15% {
left: 0;
top: 50%;
}
25% {
left: 80%;
top: 50%;
}
35% {
left: 80%;
top: 0;
}
40% {
left: 35%;
top: 0%;
}
75% {
left: 35%;
top: 15%;
}
100% {
left: 35%;
top: 15%;
}
}
#suprise {
visibility: hidden;
margin-top: 30px;
}
.secert {
visibility: hidden;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="build a house.css">
<title></title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
</head>
<body class="cf">
<div id="wrapper">
<h1>What animal is in your house?</h1>
Create a home vision
<select id="structureValue">
<option value="Roof" name="structure">Roof</option>
<option value="Building" name="structure">Building</option>
<option value="Environment" name="structure">Environment</option>
<option value="Pet" name="structure">Pet</option>
</select> Choose the details
<select id="color">
<option value="a">Gray</option>
<option value="b">Green</option>
<option value="c">Orange</option>
<option value="d">Yellow</option>
</select>
<button id="firstButton">Click Me</button>
<br>
<button id="suprise">What's in my house</button>
<div id="glide">
<div id="build">
</div>
<div id="building">
<div id="pet"></div>
</div>
</div>
<script type="text/javascript" src="build a house.js"></script>
</body>
</html>
Your code is very wrong in many aspects. Take a deep look on the code I made. It shall inspire you on how the things should be done.
var myform = document.querySelector('#houseBuilder')
var building = document.querySelector('#building')
var suprise = document.querySelector('#suprise')
var roof = document.querySelector('#roof')
var pet = document.querySelector('#pet')
myform.addEventListener('submit', function(evenet){
switch(myform.structure.value){
case 'roof':
roof.style.color = myform.color.value
break;
case 'building':
building.style.backgroundColor = myform.color.value
break;
case 'environment':
document.body.style.backgroundImage = "url('" + myform.environment.value + "')"
break;
case 'pet':
pet.src = myform.pet.value
break;
}
/* Has user allready set all of building parts? */
if(roof.style.color && building.style.backgroundColor && document.body.style.backgroundImage && pet.src){
suprise.hidden = false
}
/* Stop user from navigating */
event.preventDefault();
return false
})
myform.structure.addEventListener('change', function(){
myform.environment.hidden = true
myform.color.hidden = true
myform.pet.hidden = true
switch(myform.structure.value){
case 'environment':
myform.environment.hidden = false
break;
case 'pet':
myform.pet.hidden = false
break;
default:
myform.color.hidden = false
break;
}
})
#roof {
width: 0px;
height: 0px;
border-left: 250px solid transparent;
border-right: 250px solid transparent;
border-bottom: 350px solid;
background: none;
/* Will hide the roof until other color is set */
color: transparent;
}
#building {
width: 500px;
height: 300px;
}
body {
background-repeat: no-repeat;
background-size: 100% 100%;
background-size: cover;
}
#pet {
margin-left: 10%;
width: 80%;
}
<form id="houseBuilder" name="home">
<h1>What animal is in your house?</h1>
<label>
Create a home vision
<select name="structure">
<option value="roof">Roof</option>
<option value="building">Building</option>
<option value="environment">Environment</option>
<option value="pet">Pet</option>
</select>
</label>
<br>
<label>
Choose the details
<select name="color">
<!-- Option's value is equal to it's innerText if no value us specified -->
<option>Gray</option>
<option>Green</option>
<option>Orange</option>
<option>Yellow</option>
</select>
<select hidden name="pet">
<option value="https://media.giphy.com/media/eGOorb2NowXny/giphy.gif">Squire</option>
<option value="https://assets.horsenation.com/wp-content/uploads/2013/09/1379338067174322.gif">Chinchilla</option>
<option value="https://i0.wp.com/media.giphy.com/media/TfFbA8xkrIymk/giphy.gif?resize=500%2C281&ssl=1">Dinosaur</option>
<option value="http://s3.amazonaws.com/barkpost-assets/50+GIFs/17.gif">Dog</option>
</select>
<select hidden name="environment">
<option value="https://tpwd.texas.gov/state-parks/franklin-mountains/gallery/franklin-mnt_panorama1.jpg">Mountain</option>
<option value="https://openclipart.org/image/2400px/svg_to_png/218873/Autumn-By-The-Lake.png">Lakeside</option>
<option value="http://travel.home.sndimg.com/content/dam/images/travel/fullset/2014/12/3/top-10-caribbean-beaches-eagle-beach-aruba.jpg.rend.hgtvcom.966.725.suffix/1491584555480.jpeg">Beach</option>
<option value="http://www.jeremyrobinsononline.com/wp-content/uploads/2013/05/White_Island_New_Zealand.jpg">Island</option>
</select>
</label>
<br>
<button>Click Me</button>
</form>
<button hidden id="suprise">What's in my house</button>
<div id="glide">
<div id="roof"></div>
<div id="building">
<img id="pet">
</div>
</div>

error: Uncaught TypeError: Cannot set property 'innerHTML' of null after adding and deleting an Event

I have this unfinished tic-tac-toe game and i'm having trouble when i finish the first game, then press "iniciar" to play again. I get this innerHTML error, can't figure out why is this happening and i would really appreciate some help.
It actually works like this:
"Iniciar" to start playing
When game finishes if it's a tie
"Iniciar" again
If there is a winner the scoreboard changes.
"Iniciar" (here is when the error occurs)
"Reiniciar" resets the score and start a new game. This gives an error too.
It's weird because when it's a TIE, there's no problem with #errorenTurno
But when there's a winner and i start over, the error is there.
<html>
<head>
<link href='http://fonts.googleapis.com/css?family=Peralta' rel='stylesheet' type='text/css'>
</head>
<body>
<script type="text/javascript">
var turno = 1,
puntosX = 0,
puntosCero = 0; // some globals
window.addEventListener('load', start, false);
function start() {
document.getElementById('empezar').addEventListener('click', inicio, false); // yellow buttons
document.getElementById('reiniciar').addEventListener('click', reinicio, false);
}
function reinicio() { // yellow buttons
document.getElementById('ganX').innerHTML = 0;
document.getElementById('gandO').innerHTML = 0;
inicio();
}
function inicio() { // adds listener to all spans in the table
var x;
for (x = 0; x <= 8; x++) {
document.getElementById('boton' + x).innerHTML = '';
}
for (x = 0; x <= 8; x++) {
document.getElementById('boton' + x).addEventListener('click', jugada, false);
}
}
function jugada(evt) { // checks the move
document.getElementById('errorenTurno').innerHTML = '';
var bloqueJugado = evt.target;
if (turno === 1) {
if (bloqueJugado.innerHTML === 'O' || bloqueJugado.innerHTML === 'X') {
document.getElementById('errorenTurno').innerHTML = 'Ya se ha jugado aquíx'; // already marked
return;
} else {
if (bloqueJugado.innerHTML !== 'X') {
evt.target.innerHTML = 'X';
}
}
verificarGan('X', 1);
turno = 0;
return;
}
if (turno === 0) {
if (bloqueJugado.innerHTML === 'X' || bloqueJugado.innerHTML === 'O') {
document.getElementById('errorenTurno').innerHTML = 'Ya se ha jugado aquí0'; // already marked
return;
} else {
if (bloqueJugado.innerHTML !== 'O') {
evt.target.innerHTML = 'O';
}
}
verificarGan('O', 2);
turno = 1;
return;
}
}
function verificarGan(mov, jug) { // verifies if there is a winning move
var j1 = document.getElementById('boton0');
var j2 = document.getElementById('boton1');
var j3 = document.getElementById('boton2');
var j4 = document.getElementById('boton3');
var j5 = document.getElementById('boton4');
var j6 = document.getElementById('boton5');
var j7 = document.getElementById('boton6');
var j8 = document.getElementById('boton7');
var j9 = document.getElementById('boton8');
var detuvo = 0;
function detener(gano) { // deletes the event listener from spans in table
if (gano == 1) {
for (x = 0; x <= 8; x++) {
document.getElementById('boton' + x).removeEventListener('click', jugada);
}
}
}
function puntoTablero() { // adds points to scoreboard, since i added this i started having trouble
if (jug == 1) {
puntosX = puntosX + 1;
document.getElementById('ganX').innerHTML = puntosX;
}
if (jug == 2) {
puntosCero = puntosCero + 1;
document.getElementById('gandO').innerHTML = puntosCero;
}
}
// checking all winning moves one by one. Then it applies the needed functions.
if (j1.innerHTML == mov && j2.innerHTML == mov && j3.innerHTML == mov) {
document.getElementById('ganador').innerHTML = 'Ha ganado el jugador ' + jug;
detener(1);
puntoTablero();
}
if (j4.innerHTML == mov && j5.innerHTML == mov && j6.innerHTML == mov) {
document.getElementById('ganador').innerHTML = 'Ha ganado el jugador ' + jug;
detener(1);
puntoTablero();
}
if (j7.innerHTML == mov && j8.innerHTML == mov && j9.innerHTML == mov) {
document.getElementById('ganador').innerHTML = 'Ha ganado el jugador ' + jug;
detener(1);
puntoTablero();
}
if (j1.innerHTML == mov && j4.innerHTML == mov && j7.innerHTML == mov) {
document.getElementById('ganador').innerHTML = 'Ha ganado el jugador ' + jug;
detener(1);
puntoTablero();
}
if (j2.innerHTML == mov && j5.innerHTML == mov && j8.innerHTML == mov) {
document.getElementById('ganador').innerHTML = 'Ha ganado el jugador ' + jug;
detener(1);
puntoTablero();
}
if (j3.innerHTML == mov && j6.innerHTML == mov && j9.innerHTML == mov) {
document.getElementById('ganador').innerHTML = 'Ha ganado el jugador ' + jug;
detener(1);
puntoTablero();
}
if (j1.innerHTML == mov && j5.innerHTML == mov && j9.innerHTML == mov) {
document.getElementById('ganador').innerHTML = 'Ha ganado el jugador ' + jug;
detener(1);
puntoTablero();
}
if (j7.innerHTML == mov && j5.innerHTML == mov && j3.innerHTML == mov) {
document.getElementById('ganador').innerHTML = 'Ha ganado el jugador ' + jug;
detener(1);
puntoTablero();
}
}
</script>
<style>
.laVieja {
font-family: Peralta;
position: fixed;
left: 0px;
top: 100px;
cursor: default;
color: black;
background-color: lightgrey;
}
.laVieja td {} .laVieja span {
font-size: 100px;
display: inline-block;
border: 1px solid white;
width: 160px;
height: 160px;
text-align: center;
line-height: 150px;
}
span {
clear: both;
}
.botonZ {
font-family: Peralta;
border: 1px solid black;
text-align: center;
padding-top: 18px;
cursor: pointer;
width: 150px;
height: 40px;
background-color: lightyellow;
display: inline-block;
position: relative;
top: 90px;
left: 10px;
}
.botonZ:hover {
background-color: yellow;
}
#reiniciar {} * {
font-family: Peralta;
}
#ganador {
font-size: 30px;
border: 1px solid white;
text-align: center;
position: relative;
width: 100%;
height: 130px;
top: 80px;
display: block;
color: green;
}
#estadisticas {
width: 350px;
height: 400px;
position: fixed;
top: 100px;
left: 530px;
border: 1px solid white;
}
#ganadasX {
font-size: 20px;
}
#ganadasO {
font-size: 20px;
}
#ganX {
font-size: 30px;
color: green;
}
#gandO {
font-size: 30px;
color: red;
}
</style>
<table border="1" class="laVieja">
<tr>
<td><span id="boton0">1</span>
</td>
<td><span id="boton1">2</span>
</td>
<td><span id="boton2">3</span>
</td>
</tr>
<tr>
<td><span id="boton3">4</span>
</td>
<td><span id="boton4">5</span>
</td>
<td><span id="boton5">6</span>
</td>
</tr>
<tr>
<td><span id="boton6">7</span>
</td>
<td><span id="boton7">8</span>
</td>
<td><span id="boton8">9</span>
</td>
</table>
<div id="estadisticas">
<p><span id="ganadasX">Ganadas X:&nbsp&nbsp </span><span id="ganX">10</span>
</p>
<p><span id="ganadasO">Ganadas O:&nbsp&nbsp </span><span id="gandO">5</span>
</p>
<p><span id="ganador"><span id="errorenTurno"></span></span>
</p>
<div id="empezar" class="botonZ">Iniciar</div>
<div id="reiniciar" class="botonZ">Reiniciar Juego</div>
</div>
</tr>
</body>
</html>
While checking your inner moves the innerHTML of the div with id ganador is replaced by Ha ganado el jugador. SO now what happens is that the span with id errorenTurno is lost.
Your errorenTurno span is inside the ganador span.
<p><span id="ganador"><span id="errorenTurno"></span></span>
So either you have to append the message to ganador or move out the errorenTurno span out side of ganador. once the message is displayed there is no longer an element named errorenTurno
Add a null check to element before using it:
function jugada(evt) { // checks the move
if(document.getElementById('errorenTurno')!== null )
document.getElementById('errorenTurno').innerHTML = '';
and initialize x variable used in loop using var keyword:
function detener(gano) { // deletes the event listener from spans in table
if (gano == 1) {
for (var x = 0; x <= 8; x++) {
document.getElementById('boton' + x).removeEventListener('click', jugada);
}
}
}
and your html contain not closed tr tag and an extra tr close tag just before html end:
<tr>
<td><span id="boton6">7</span>
</td>
<td><span id="boton7">8</span>
</td>
<td><span id="boton8">9</span>
</td>
<!-- add here closing tr tag-->
</tr>
</table>
Here is Demo JsFiddle

Categories