When I type in something in the text area element and then click on the read button nothing is being uttered. The console doesn't throw any error and I can't identify where I've gone wrong either. I went on the "SpeechUtterance" MDN documentation and as far as I can tell I've followed all the right steps. Help please!
const read = document.getElementById("read");
const pause = document.getElementById("pause");
const stop = document.getElementById("stop");
const speed = document.getElementById("speed");
const text = document.getElementById("text");
read.addEventListener("click", () => {
readText(text.value)
});
pause.addEventListener("click", () => {
pauseText();
});
function readText(dummy) {
var utterThis = new SpeechSynthesisUtterance(dummy);
if(speechSynthesis.speaking && speechSynthesis.paused) {
return speechSynthesis.resume()
}
if(speechSynthesis.speaking) return;
console.log(utterThis)
console.log(speechSynthesis)
utterThis.text = dummy;
utterThis.rate = speed.value
text.disabled = true;
speechSynthesis.speak(utterThis)
utterThis.addEventListener("end", () => {
text.disabled = false
})
}
function pauseText() {
if(speechSynthesis.speaking) speechSynthesis.pause();
}
body {
background-color: purple;
}
textarea {
margin-top: 50px;
margin: auto;
}
textarea:focus {
background: green;
}
.container {
display: flex;
justify-content: center;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="index.css">
<title></title>
</head>
<body>
<textarea id="text" name="name" rows="30" cols="100"></textarea>
<div class="container">
<label for="speed">Speed</label>
<input id="speed" type="number" min="0" step="1" max="10">
<button id="read" type="button" name="button">Read</button>
<button id="pause" type="button" name="button">Pause</button>
<button id="stop" type="button" name="button">Stop</button>
</div>
</body>
<script src="index.js" charset="utf-8"></script>
</html>
Related
i want my "detail" button to show the text hidden through overflow but i don't know how to access it. I tried to access it through previousSibling and nextSibling of my button but it doesn't work. I also did it with querySelectorAll but it changes all of my appended "p" instead of just the one linked to the button i click on
let add = document.getElementById("addNote");
let resultat = document.getElementById("result");
let y=1;
var addANote = function () {
let contenu = document.getElementById("saisie").value;
let resultat = document.getElementById("resultat");
var newP = document.createElement("p");
var newText1 = document.createTextNode(`Note ${y} \n ${contenu}`);
newP.setAttribute("overflow", "hidden");
var bouton = document.createElement('button');
bouton.innerHTML ="Details";
newP.appendChild(newText1);
document.getElementById("result").appendChild(newP);
document.getElementById("result").appendChild(bouton);
bouton.addEventListener("click", function() {
bouton.previousSibling.setAttribute("overflow", "visible");
});
}
add.addEventListener("click", function() {
addANote();
y++;
})
add.onclick = function(event){
event.preventDefault()
};
#saisie {
height : 250px;
width: 75%;
}
p {
white-space: nowrap;
width: 200px;
overflow: hidden;
text-overflow: ellipsis;
}
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="popup.css">
<title>PopUp</title>
<script src='popup.js' defer></script>
</head>
<body>
<div id="content">
<form>
<h1> Note Taker</h1>
<h2>Add a new note:</h2>
<p>Note: </p>
<textarea type="text" id="saisie" name="saisie" required minlength ="1" maxlength ="3000" size ="500"></textarea>
</br>
</br>
<button type="submit" id="addNote"> Ajouter une Note </button>
</form>
<br>
<br>
<div class="autoShowHide" id="result"></div>
</div>
</body>
</html>
Overflow isn't an attribute, it's a style.
You can revert on a second click by checking the current style of the element in an if statement.
let add = document.getElementById("addNote");
let resultat = document.getElementById("result");
let y = 1;
var addANote = function() {
let contenu = document.getElementById("saisie").value;
let resultat = document.getElementById("resultat");
var newP = document.createElement("p");
var newText1 = document.createTextNode(`Note ${y} \n ${contenu}`);
newP.style.overflow = "hidden";
var bouton = document.createElement('button');
bouton.innerHTML = "Plus Details";
newP.appendChild(newText1);
document.getElementById("result").appendChild(newP);
document.getElementById("result").appendChild(bouton);
bouton.addEventListener("click", function() {
let style = bouton.previousSibling.style;
if (style.overflow == "visible") {
style.overflow = "hidden";
bouton.innerHTML = "Plus Details";
} else {
style.overflow = "visible";
bouton.innerHTML = "Moin Details";
}
});
}
add.addEventListener("click", function(e) {
e.preventDefault();
addANote();
y++;
})
#saisie {
height: 250px;
width: 75%;
}
p {
white-space: nowrap;
width: 200px;
overflow: hidden;
text-overflow: ellipsis;
}
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="popup.css">
<title>PopUp</title>
<script src='popup.js' defer></script>
</head>
<body>
<div id="content">
<form>
<h1> Note Taker</h1>
<h2>Add a new note:</h2>
<p>Note: </p>
<textarea type="text" id="saisie" name="saisie" required minlength="1" maxlength="3000" size="500"></textarea>
</br>
</br>
<button type="submit" id="addNote"> Ajouter une Note </button>
</form>
<br>
<br>
<div class="autoShowHide" id="result"></div>
</div>
</body>
</html>
let doorLeft = document.getElementById("left");
let doorMiddle = document.getElementById("middle");
let doorRight = document.getElementById("right");
let resetButton = document.getElementById("reset");
let numberOfClicks = 0;
function incrementClicks() {
numberOfClicks++;
console.log('Number of clicks: ' + numberOfClicks)
}
/* -------------------------------------------------------------------------- */
/* handle click door only once */
/* -------------------------------------------------------------------------- */
const revealDoorColour = () => {
doorLeft.addEventListener(
"click",
() => {
incrementClicks();
}, {
once: true,
}
);
doorMiddle.addEventListener(
"click",
() => {
incrementClicks();
}, {
once: true,
}
);
doorRight.addEventListener(
"click",
() => {
incrementClicks();
}, {
once: true,
}
);
};
/* -------------------------------------------------------------------------- */
const reset = () => {
doorLeft.style.backgroundColor = "paleturquoise";
doorRight.style.backgroundColor = "paleturquoise";
doorMiddle.style.backgroundColor = "paleturquoise";
revealDoorColour();
resetButton.innerHTML = "Let's play";
};
resetButton.addEventListener("click", function() {
reset();
numberOfClicks = 0;
});
.container.main {
display: flex;
justify-content: space-around;
padding: 0 20%;
}
.door {
height: 500px;
width: 300px;
margin: 10px;
}
#left {
background-color: paleturquoise;
}
#middle {
background-color: paleturquoise;
}
#right {
background-color: paleturquoise;
}
.score {
text-align: center;
}
<!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>Door guesser</title>
<script src="./js/main.js" async></script>
<link rel="stylesheet" href="./css/style.css">
</head>
<body>
<div class="container main">
<div class="door" id="left">
</div>
<div class="door" id="middle">
</div>
<div class="door" id="right">
</div>
</div>
<div class="container score">
<div class="currentScoreGroup">
<div>Current score: </div>
<div id="currentScore">0</div>
</div>
<div class="bestScoreGroup">
<div>Best score: </div>
<div id="bestScore">0</div>
</div>
<button class="reset" id='reset'>Let's play </button>
</div>
</body>
</html>
Following Extract function from addEventListener I've added the {once:true} parameter which seems to work fine most of the time. However, when clicking on the div in question, it randomly gets fired multiple times (at the same x/y coordinates). How is this possible? I set a breakpoint in the anonymous function and it runs through it multiple times. Any ideas?
To replicate the issue
Click Let's play
Click any card
click Let's play once again
Click a different card
Now you should see 2 entries (clicks) in the console
The once option of addEventListener work like this:
once
A Boolean indicating that the listener should be invoked at most once after being added.
If true, the listener would be automatically removed when invoked.
So if a div is not clicked, its handler still stay there. When you click play again, you basically add more event listener to the div. What why it randomly gets fired multiple times (at the same x/y coordinates)
To fix that, just remove the event listener in reset
let doorLeft = document.getElementById("left");
let doorMiddle = document.getElementById("middle");
let doorRight = document.getElementById("right");
let resetButton = document.getElementById("reset");
let numberOfClicks = 0;
function incrementClicks() {
numberOfClicks++;
console.log('Number of clicks: ' + numberOfClicks)
}
/* -------------------------------------------------------------------------- */
/* handle click door only once */
/* -------------------------------------------------------------------------- */
const revealDoorColour = () => {
doorLeft.removeEventListener("click", incrementClicks);
doorMiddle.removeEventListener("click", incrementClicks);
doorRight.removeEventListener("click", incrementClicks);
//
doorLeft.addEventListener("click", incrementClicks, { once: true });
doorMiddle.addEventListener("click", incrementClicks, { once: true });
doorRight.addEventListener("click", incrementClicks, { once: true });
};
/* -------------------------------------------------------------------------- */
const reset = () => {
doorLeft.style.backgroundColor = "paleturquoise";
doorRight.style.backgroundColor = "paleturquoise";
doorMiddle.style.backgroundColor = "paleturquoise";
revealDoorColour();
resetButton.innerHTML = "Let's play";
};
resetButton.addEventListener("click", function() {
reset();
numberOfClicks = 0;
});
.container.main {
display: flex;
justify-content: space-around;
padding: 0 20%;
}
.door {
height: 500px;
width: 300px;
margin: 10px;
}
#left {
background-color: paleturquoise;
}
#middle {
background-color: paleturquoise;
}
#right {
background-color: paleturquoise;
}
.score {
text-align: center;
}
<!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>Door guesser</title>
<script src="./js/main.js" async></script>
<link rel="stylesheet" href="./css/style.css">
</head>
<body>
<div class="container main">
<div class="door" id="left">
</div>
<div class="door" id="middle">
</div>
<div class="door" id="right">
</div>
</div>
<div class="container score">
<div class="currentScoreGroup">
<div>Current score: </div>
<div id="currentScore">0</div>
</div>
<div class="bestScoreGroup">
<div>Best score: </div>
<div id="bestScore">0</div>
</div>
<button class="reset" id='reset'>Let's play </button>
</div>
</body>
</html>
Here I am trying to run a function "renderQuestion" which will randomize questions and will show the next options once the "next" button is clicked. By "getSelectedValue" I am trying to get the selected radio button.
But what I am fetching is that it shows which button is selected for the first time I press "next" button, but it's not working onward. It's giving some error "Cannot read property 'value' of null".
If I don't use "renderForm.reset()", I can get the values every time I click next. Now, what I am doing wrong here?
const renderForm = document.querySelector("#renderForm");
const next = document.querySelector("#next");
// const q = document.querySelector("#question");
// const ans1 = document.querySelector("#ans1");
// const ans2 = document.querySelector("#ans2");
// const ans3 = document.querySelector("#ans3");
// const ans4 = document.querySelector("#ans4");
renderQuestion = async () => {
const timeout = async (ms) => new Promise((res) => setTimeout(res, ms));
let userClicked = false;
let arr = [ans1, ans2, ans3, ans4]; //array of options
for (let i = arr.length - 1; i > 0; i--) { ////randomizing array
const j = Math.floor(Math.random() * (i + 1));
const temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// q.innerHTML =
// `${totalQ}/${ongoing}` + ` ` + qID.data().question;
// arr[0].innerHTML = qID.data().a;
// arr[1].innerHTML = qID.data().b;
// arr[2].innerHTML = qID.data().c;
// arr[3].innerHTML = qID.data().d;
next.addEventListener("click", (e) => {
console.log("inside next");
let getSelectedValue = document.querySelector('input[name="ans"]:checked');
console.log(getSelectedValue.value);
getSelectedValue.checked = false;
userClicked = true;
e.preventDefault();
// renderForm.reset();
});
while (userClicked === false) await timeout(50);
};
start = async () =>
{
for(let i=0;i<4;i++)
{
await renderQuestion();
}
}
start();
#renderForm p {
display: inline;
}
.option {
/* display: inline-block; */
font-size: 1.5rem;
margin-block: 2rem;
margin-left: 1rem;
}
.button {
border: none;
outline: none;
font-size: 1rem;
margin-top: 1rem;
background-color: #081b0a;
color: #ffffff;
padding: 0.75rem 1rem;
border-radius: 0.5rem;
font-weight: 100;
font-family: monospace;
margin-bottom:8rem;
}
<!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" />
<link rel="stylesheet" href="/style.css" />
<title>Document</title>
</head>
<body>
<section>
<form action="" id="renderForm">
<p id="question"></p>
<div class="option">
<input type="radio" name="ans" id="option1" value="ans1" required />
<p id="ans1">1</p>
</div>
<div class="option">
<input type="radio" name="ans" id="option2" value="ans2" required />
<p id="ans2">2</p>
</div>
<div class="option">
<input type="radio" name="ans" id="option3" value="ans3" required />
<p id="ans3">3</p>
</div>
<div class="option">
<input type="radio" name="ans" id="option4" value="ans4" required />
<p id="ans4">4</p>
</div>
<button class="button" id="next" type="submit">Next</button>
</form>
</section>
<script src="/js.js"></script>
</body>
</html>
Move the eventlistener out of the loop. You only need to apply it once, and if you delegate it (meaning apply the listener to a static parent, like document and then test for the target ID), it will work for any #next button you add to the DOM.
document.addEventListener("click", (e) => {
if (e.target.id !== 'next') return
console.log("inside next");
let getSelectedValue = document.querySelector('input[name="ans"]:checked');
console.log(getSelectedValue.value);
getSelectedValue.checked = false;
userClicked = true;
e.preventDefault();
// renderForm.reset();
});
const renderForm = document.querySelector("#renderForm");
const next = document.querySelector("#next");
document.addEventListener("click", (e) => {
if (e.target.id !== 'next') return
console.log("inside next");
let getSelectedValue = document.querySelector('input[name="ans"]:checked');
console.log(getSelectedValue.value);
getSelectedValue.checked = false;
userClicked = true;
e.preventDefault();
// renderForm.reset();
});
renderQuestion = async() => {
const timeout = async(ms) => new Promise((res) => setTimeout(res, ms));
let userClicked = false;
let arr = [ans1, ans2, ans3, ans4]; //array of options
for (let i = arr.length - 1; i > 0; i--) { ////randomizing array
const j = Math.floor(Math.random() * (i + 1));
const temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
while (userClicked === false) await timeout(50);
};
start = async() => {
for (let i = 0; i < 4; i++) {
await renderQuestion();
}
}
start();
#renderForm p {
display: inline;
}
.option {
/* display: inline-block; */
font-size: 1.5rem;
margin-block: 2rem;
margin-left: 1rem;
}
.button {
border: none;
outline: none;
font-size: 1rem;
margin-top: 1rem;
background-color: #081b0a;
color: #ffffff;
padding: 0.75rem 1rem;
border-radius: 0.5rem;
font-weight: 100;
font-family: monospace;
margin-bottom: 8rem;
}
<!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" />
<link rel="stylesheet" href="/style.css" />
<title>Document</title>
</head>
<body>
<section>
<form action="" id="renderForm">
<p id="question"></p>
<div class="option">
<input type="radio" name="ans" id="option1" value="ans1" required />
<p id="ans1">1</p>
</div>
<div class="option">
<input type="radio" name="ans" id="option2" value="ans2" required />
<p id="ans2">2</p>
</div>
<div class="option">
<input type="radio" name="ans" id="option3" value="ans3" required />
<p id="ans3">3</p>
</div>
<div class="option">
<input type="radio" name="ans" id="option4" value="ans4" required />
<p id="ans4">4</p>
</div>
<button class="button" id="next" type="submit">Next</button>
</form>
</section>
<script src="/js.js"></script>
</body>
</html>
At last, I have solved the issue. Initially "renderQuestion" was working every time (4 times here because of for loop) I clicked the "next" button. But whenever I move the eventlistener out of the loop "renderQuestion" function wasn't working on the "next" button click.
It's Because "userClicked" is a local variable and isn't being triggered if I click "next". So, I just changed it to a global variable and everything else same as #kinglish did.
const renderForm = document.querySelector("#renderForm");
const next = document.querySelector("#next");
document.addEventListener("click", (e) => {
if (e.target.id !== 'next') return
console.log("inside next");
let getSelectedValue = document.querySelector('input[name="ans"]:checked');
console.log(getSelectedValue.value);
getSelectedValue.checked = false;
userClicked = true;
e.preventDefault();
// renderForm.reset();
});
renderQuestion = async() => {
console.log("render");
const timeout = async(ms) => new Promise((res) => setTimeout(res, ms));
window.userClicked = false;
let arr = [ans1, ans2, ans3, ans4]; //array of options
for (let i = arr.length - 1; i > 0; i--) { ////randomizing array
const j = Math.floor(Math.random() * (i + 1));
const temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
while (userClicked === false) await timeout(50);
};
start = async() => {
for (let i = 0; i < 4; i++) {
await renderQuestion();
}
}
start();
#renderForm p
{
display: inline;
}
.option
{
/* display: inline-block; */
font-size: 1.5rem;
margin-block: 2rem;
margin-left: 1rem;
}
.button {
border: none;
outline: none;
font-size: 1rem;
margin-top: 1rem;
background-color: #081b0a;
color: #ffffff;
padding: 0.75rem 1rem;
border-radius: 0.5rem;
font-weight: 100;
font-family: monospace;
margin-bottom:8rem;
}
<!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" />
<link rel="stylesheet" href="/style.css" />
<title>Document</title>
</head>
<body>
<section>
<form action="" id="renderForm">
<p id="question"></p>
<div class="option">
<input type="radio" name="ans" id="option1" value="ans1" required />
<p id="ans1">1</p>
</div>
<div class="option">
<input type="radio" name="ans" id="option2" value="ans2" required />
<p id="ans2">2</p>
</div>
<div class="option">
<input type="radio" name="ans" id="option3" value="ans3" required />
<p id="ans3">3</p>
</div>
<div class="option">
<input type="radio" name="ans" id="option4" value="ans4" required />
<p id="ans4">4</p>
</div>
<button class="button" id="next" type="submit">Next</button>
</form>
</section>
<script src="/js.js"></script>
</body>
</html>
I'm trying to get the two players to take turns in my tic-tac-toe project. In my playerContols function I've tried to put each player in a "current PLayer" housing variable that will switch out depending if one player went already but it just gets stuck on player 2 and just mark every cell with O's. I'm not entirely sure what's wrong with it
my code
const playgame = (() => {
const playerOne = {
Name: 'playerOne',
Marking: 'X'
};
const playerTwo = {
Name: 'PlayerTwo',
Marking: 'O'
};
function playerControls(e) {
let currentPlayer;
currentPlayer = playerOne;
e.target.textContent = currentPlayer.Marking;
if (currentPlayer === playerOne) {
currentPlayer = playerTwo;
e.target.textContent = currentPlayer.Marking;
} else {
currentPlayer = playerOne;
e.target.textContent = currentPlayer.Marking;
}
}
return {
playerControls
}
})();
const gameBoard = (() => {
const makeBoard = (rows, cols) => {
const theBoard = document.getElementById("GameBoard");
theBoard.style.gridTemplateColumns = `repeat(${cols}, 1fr)`;
theBoard.style.gridTemplateRows = `repeat(${rows}, 1fr)`;
for (i = 0; i < (rows * cols); i++) {
let gameDivs = document.createElement("div");
gameDivs.addEventListener("click", playgame.playerControls)
theBoard.appendChild(gameDivs).classList.add("newdivgrid");
}
};
makeBoard(3, 3);
})();
#GameBoard {
width: 600px;
height: 350px;
border: 1px solid darkblue;
margin-left: 27%;
text-align: center;
font-size: 500%;
font-family: cursive, sans-serif;
display: grid;
}
.newdivgrid {
border: 1px solid black;
grid-row-gap: 50px;
}
.newdivgrid:hover {
background-color: aqua;
}
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tic-Tac-Toe game</title>
<link rel="stylesheet" href="Tic-Tac-Toe.css">
</head>
<h1>Tic-Tac-Toe Project</h1>
<div id="PlayerSelectionContainer">
<h2>Select Players</h2>
<div class="Player1">
<h3>Player 1</h3>
<div class="playerSelectionButtons" data-player="playerOne">
<button data-player="human">Human</button>
<button data-player="computer">Computer</button>
</div>
</div>
<div class="Player2">
<h3>Player 2</h3>
<div class="playerSelectionButtons" data-player="playerTwo">
<button data-human-player="human">Human</button>
<button data-computer-player="computer">Computer</button>
</div>
</div>
</div>
<div id="GameBoard">
</div>
<div id="resultContainer">
<h3>Results</h3>
<div class="player1Results">
<h3>Player 1 Results</h3>
<textarea placeholder="0" disabled></textarea>
</div>
<div class="Player2Results">
<h3>Player 2 Results</h3>
<textarea placeholder="0" disabled></textarea>
</div>
</div>
<body>
<script src="Tic-Tac-Toe.js"></script>
</body>
</html>
The issue is that your currentPlayer variable declaration and initialization needs to live outside the playerControls function or else you're just resetting it to playerOne each time.
let currentPlayer;
currentPlayer = playerOne;
function playerControls(e){...}
Here is the fix in action:
const playgame = (()=> {
const playerOne = {
Name: 'playerOne',
Marking: 'X'
};
const playerTwo = {
Name: 'PlayerTwo',
Marking: 'O'
};
let currentPlayer;
currentPlayer = playerOne;
function playerControls(e){
e.target.textContent = currentPlayer.Marking;
if(currentPlayer === playerOne)
{
currentPlayer = playerTwo;
e.target.textContent = currentPlayer.Marking;
}else{
currentPlayer = playerOne;
e.target.textContent = currentPlayer.Marking;
}
}
return{playerControls}
})();
const gameBoard = (() => {
const makeBoard = (rows, cols) => {
const theBoard = document.getElementById("GameBoard");
theBoard.style.gridTemplateColumns = `repeat(${cols}, 1fr)`;
theBoard.style.gridTemplateRows = `repeat(${rows}, 1fr)`;
for (i=0; i<(rows * cols); i++){
let gameDivs = document.createElement("div");
gameDivs.addEventListener("click", playgame.playerControls)
theBoard.appendChild(gameDivs).classList.add("newdivgrid");
}
};
makeBoard(3,3);
})();
#GameBoard{
width: 600px;
height: 350px;
border: 1px solid darkblue;
margin-left: 27%;
text-align: center;
font-size: 500%;
font-family: cursive, sans-serif;
display: grid;
}
.newdivgrid{
border: 1px solid black;
grid-row-gap: 50px;
}
.newdivgrid:hover{
background-color: aqua;
}
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tic-Tac-Toe game</title>
<link rel="stylesheet" href="Tic-Tac-Toe.css">
</head>
<h1>Tic-Tac-Toe Project</h1>
<div id="PlayerSelectionContainer">
<h2>Select Players</h2>
<div class="Player1">
<h3>Player 1</h3>
<div class="playerSelectionButtons" data-player="playerOne">
<button data-player="human">Human</button>
<button data-player="computer">Computer</button>
</div>
</div>
<div class="Player2">
<h3>Player 2</h3>
<div class="playerSelectionButtons" data-player="playerTwo">
<button data-human-player="human">Human</button>
<button data-computer-player="computer">Computer</button>
</div>
</div>
</div>
<div id="GameBoard">
</div>
<div id="resultContainer">
<h3>Results</h3>
<div class="player1Results">
<h3>Player 1 Results</h3>
<textarea placeholder="0" disabled ></textarea>
</div>
<div class="Player2Results">
<h3>Player 2 Results</h3>
<textarea placeholder="0" disabled ></textarea>
</div>
</div>
<body>
<script src="Tic-Tac-Toe.js"></script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>stoplight</title>
<link rel="stylesheet" type="text/css" href="stoplight.css">
</head>
<body>
<div id="controls">
<button id="stop">Stop</button>
<button id="slow">Slow</button>
<button id="go">Go</button>
<button id="caution">Caution</button>
</div>
<div id="mainContainer">
<div id="top" class="off">
</div>
<div id="middle" class="off">
</div>
<div id="bottom" class="off">
</div>
</div>
<script type="text/javascript" src="stoplight.js"></script>
</body>
</html>
Basically, I'm just trying to select each div of the stoplight and change the background color. First, I thought I could just reset each div to its original color. I'm trying to do the same with the setInterval function that starts a flashing yellow light, but it doesn't seem to stop it and breaks the rest of the functions.
document.getElementById('stop').onclick = goRed;
document.getElementById('go').onclick = goGreen;
document.getElementById('slow').onclick = goYellow;
document.getElementById('caution').addEventListener('click', () => {
blink();
});
let middle = document.getElementById('middle');
let blinking;
function goRed() {
reset();
document.getElementById('top').style.backgroundColor = '#FF0000';
};
function goYellow() {
reset();
middle.style.backgroundColor = '#FFFF00';
};
function goGreen() {
reset();
document.getElementById('bottom').style.backgroundColor = '#7FFF00';
};
function blink(){
reset();
blinking = setInterval(() => {
middle.classList.toggle('onYellow');
}, 1000);
};
function reset() {
document.getElementById('top').style.backgroundColor = '#A0522D';
document.getElementById('middle').style.backgroundColor = '#A0522D';
document.getElementById("bottom").style.backgroundColor = '#A0522D';
clearInterval(blinking);
};
You are mixing in-style coloring, with class based coloring, and in some cases, the browser will decide which gets a priority. Unless you add !important in the class background to enforce the attribute.
I suggest removing all in-style coloring and sticking only to classes so that you will not have to use !important.
This way, it is easier to work with blinking and setInterval.
See my code snippet below.
document.getElementById('stop').onclick = goRed;
document.getElementById('go').onclick = goGreen;
document.getElementById('slow').onclick = goYellow;
document.getElementById('caution').addEventListener('click', () => {
blink();
});
let middle = document.getElementById('middle');
let blinking;
function goRed() {
reset();
document.getElementById('top').className = "onRed";
};
function goYellow() {
reset();
middle.className = "onYellow";
};
function goGreen() {
reset();
document.getElementById('bottom').className = "onGreen";
};
function blink() {
reset();
blinking = setInterval(() => {
middle.classList.toggle('onYellow');
middle.classList.toggle('onOff');
}, 1000);
};
function reset() {
document.getElementById('top').className = "onOff";
document.getElementById('middle').className = "onOff";
document.getElementById("bottom").className = "onOff";
clearInterval(blinking);
};
#mainContainer div {
border: 1px solid grey;
width: 40px;
height: 40px;
border-radius: 40px;
}
.onYellow {
background-color: #ffff00;
}
.onOff {
background-color: #A0522D;
}
.onGreen {
background-color: #7FFF00;
}
.onRed {
background-color: #FF0000;
}
<!DOCTYPE html>
<html>
<head>
<title>stoplight</title>
<link rel="stylesheet" type="text/css" href="stoplight.css">
</head>
<body>
<div id="controls">
<button id="stop">Stop</button>
<button id="slow">Slow</button>
<button id="go">Go</button>
<button id="caution">Caution</button>
</div>
<div id="mainContainer">
<div id="top" class="off">
</div>
<div id="middle" class="off">
</div>
<div id="bottom" class="off">
</div>
</div>
<script type="text/javascript" src="stoplight.js"></script>
</body>
</html>