How to start a function ONLY on a button click - javascript

I am looking to have my grid style game start once I click the start button on my page. Currently the game starts as soon as I click the grid, but I want this function to be invoked only when the you click the Start Button.
I already created my game Board. Which can be called using this function: createBoard(). Styling for this board is full of my divs and working.
I tried the solutions previously given in my other thread and still had an issue with the function not invoking only at the click of a start button.
Here is my replit: Any feedback on what I'm doing wrong? Thanks! :)
https://replit.com/#batb/WholeFrostyLocus
document.addEventListener('DOMContentLoaded', () => {
const grid = document.querySelector('.grid')
const startBtn = document.querySelector('.button-one')
const pauseBtn = document.querySelector('.button-two')
const scoreDisplay = document.querySelector('.score')
const countdown = document.querySelector('.countdown')
let paused = true
let score = 100
const width = 8
const squares = []
let isGameOver = false
let buzzyAmount = 12
let result = 0
const fiBuzz = [
'url(images/purple-fizzy.png)',
'url(images/buzzy-green.png)',
'url(images/new-moo-buzzy.png)',
'url(images/new-shiny-fizzy.png)'
]
//shuffled Arrays
function createBoard() {
const buzzArray = Array(buzzyAmount).fill('buzzy')
const emptyArray = Array(width * width - buzzyAmount).fill('valid')
const gameArray = emptyArray.concat(buzzArray)
const shuffledArray = gameArray.sort(() => Math.random() - 0.5)
for (let i = 0; i < width * width; i++) {
let randomNumber = Math.floor(Math.random() * fiBuzz.length)
let square = document.createElement('div')
square.setAttribute('id', i)
square.setAttribute('draggable', 'true')
square.classList.add(shuffledArray[i])
grid.appendChild(square)
squares.push(square)
square.style.backgroundImage = fiBuzz[randomNumber]
//normal click
square.addEventListener('click', function(e) {
click(square)
})
}
}
createBoard()
//check neighboring squares once square is clicked
function checkSquare(square, currentId) {
const isLeftEdge = (currentId % width === 0)
const isRightEdge = (currentId % width === width -1)
setTimeout(() => {
if (currentId > 0 && !isLeftEdge) {
const newId = squares[parseInt(currentId) -1].id
//const newId = parseInt(currentId) - 1 ....refactor
const newSquare = document.getElementById(newId)
click(newSquare)
}
if (currentId > 7 && !isRightEdge) {
const newId = squares[parseInt(currentId) +1 -width].id
//const newId = parseInt(currentId) +1 -width ....refactor
const newSquare = document.getElementById(newId)
click(newSquare)
}
if (currentId > 10) {
const newId = squares[parseInt(currentId -width)].id
//const newId = parseInt(currentId) -width ....refactor
const newSquare = document.getElementById(newId)
click(newSquare)
}
if (currentId > 11 && !isLeftEdge) {
const newId = squares[parseInt(currentId) -1 -width].id
//const newId = parseInt(currentId) -1 -width ....refactor
const newSquare = document.getElementById(newId)
click(newSquare)
}
if (currentId < 38 && !isRightEdge) {
const newId = squares[parseInt(currentId) +1].id
//const newId = parseInt(currentId) +1 ....refactor
const newSquare = document.getElementById(newId)
click(newSquare)
}
if (currentId < 40 && !isLeftEdge) {
const newId = squares[parseInt(currentId) -1 +width].id
//const newId = parseInt(currentId) -1 +width ....refactor
const newSquare = document.getElementById(newId)
click(newSquare)
}
if (currentId < 45 && !isRightEdge) {
const newId = squares[parseInt(currentId) +1 +width].id
//const newId = parseInt(currentId) +1 +width ....refactor
const newSquare = document.getElementById(newId)
click(newSquare)
}
if (currentId < 48) {
const newId = squares[parseInt(currentId) +width].id
//const newId = parseInt(currentId) +width ....refactor
const newSquare = document.getElementById(newId)
click(newSquare)
}
}, 10)
}
// game over
function gameOver(square) {
scoreDisplay.innerHTML = score + '<br>'+ ' You Lose :('
isGameOver = true
clearInterval(timerId)
// show ALL the badStars in gameOver
squares.forEach(square => {
if (square.classList.contains('buzzy')) {
square.appendChild(document.createElement('img')).src = 'images/fizz-buzz-mix.png'
square.classList.remove('buzzy')
square.classList.add('checked')
clearInterval(timerId)
}
})
}
function checkForWin() {
let matches = 0
for (let i = 0; i < squares.length; i++) {
if (score >= 100) {
scoreDisplay.innerHTML = score + ': ' + ' You Win!'
} else {
scoreDisplay.innerHTML = score + ': ' + ' You Lose!'
}
clearInterval(timerId)
}
}
// TIMER LOGIC
const startingMinutes = .25
let time = startingMinutes * 60
let timerId
let square
function countDown() {
let minutes = Math.floor(time / 60)
let seconds = time % 60
time--
console.log(minutes, 'minutes:', seconds, 'seconds')
if (time <= 0) {
checkForWin()
gameOver()
}
countdown.innerHTML = minutes + ' minutes ' + ': ' + seconds + ' seconds '
}
// add to right click
function click(square) {
let currentId = square.id
if (isGameOver) return
if (square.classList.contains('checked')) return score++
if (square.classList.contains('buzzy')) {
gameOver(square)
} else {
let total = square.getAttribute('data')
if (total !=0) {
square.classList.add('checked')
if (total == 1) square.classList.add('one')
if (total == 2) square.classList.add('two')
if (total == 3) square.classList.add('three')
if (total == 4) square.classList.add('four')
square.innerHTML = total
return
}
checkSquare(square, currentId)
}
square.classList.add('checked')
}
// START AND PAUSE LOGIC
function scoreFunction() {
if(square.classList.contains('valid')) {
score+=3
}
}
startBtn.addEventListener('click', () => {
if (paused === false) {
score++
return
}
scoreDisplay.innerHTML = 'Score' + ': ' + score++
paused = false
timerId = setInterval(countDown, 1000)
})
function pauseGame() {
paused = true
clearInterval(timerId)
}
pauseBtn.addEventListener('click', () => {
pauseGame()
})
})

Try changing up your html button so it calls the function you want once you click the button:
<button class="button-one" onclick="function_name"> Start </button>
instead of fucntion_name put the name of the function you want to call on the button click.

Related

a slide to use on the mobile web

The problem here is that when you reach the last item by doing a touch move,
If you touch move with the previous item, it doesn't work.
function slideCustom () {
const listWrap = document.querySelector('.list-item-wrap');
const listItem = document.querySelector('.list-item-wrap .list-item');
const listItems = document.querySelectorAll('.list-item-wrap .list-item');
const listItemPrev = document.querySelector('.m-slide-list-wrap .list-prev-btn');
const listItemNext = document.querySelector('.m-slide-list-wrap .list-next-btn');
const listItemCount = listItems.length;
const listItemWidth = listItem.offsetWidth;
let currentIndex = 0;
let touchStartX = null;
listWrap.style.width = listItemWidth * listItemCount + 'px';
function moveSlide(num) {
listWrap.style.left = -(num * ( listItemWidth + 10 )) + 'px';
currentIndex = num;
}
listItems.forEach((item, index) => {
item.addEventListener('click', function() {
moveSlide(index);
listItems.forEach(i => i.classList.remove('active'));
this.classList.add('active');
});
});
moveSlide(currentIndex);
listItemPrev.addEventListener('click', () => {
if (currentIndex > 0) {
moveSlide(currentIndex - 1);
listItems[currentIndex + 1].classList.remove("active");
listItems[currentIndex].classList.add("active");
}
});
listItemNext.addEventListener('click', () => {
if (currentIndex < listItemCount - 1) {
moveSlide(currentIndex + 1);
listItems[currentIndex - 1].classList.remove("active");
listItems[currentIndex].classList.add("active");
}
});
if (listItemCount < 2) {
listItemPrev.remove();
listItemNext.remove();
}
listWrap.addEventListener('touchstart', (event) => {
touchStartX = event.touches[0].clientX;
});
listWrap.addEventListener('touchmove', (event) => {
let touchMoveX = event.touches[0].clientX;
let touchDiffX = touchMoveX - touchStartX;
if (touchStartX !== null) {
if (touchDiffX > 0 && currentIndex > 0) {
moveSlide(currentIndex - 1);
listItems[currentIndex + 1].classList.remove("active");
listItems[currentIndex].classList.add("active");
} else if (touchDiffX < 0 && currentIndex < listItemCount - 1) {
moveSlide(currentIndex + 1);
listItems[currentIndex - 1].classList.remove("active");
listItems[currentIndex].classList.add("active");
} else if (touchDiffX < 0 && currentIndex === listItemCount - 1) {
moveSlide(currentIndex);
} else if (touchDiffX > 0 && currentIndex === 0) {
moveSlide(currentIndex);
}
touchStartX = null;
}
});
}
For example, assuming that there are 7 items,
When you touch move from right to left and reach the last 7th item,
I want to touch move the 7th item from left to right and move to the previous 6th item.

How do I update div when the text content changes in React

I am creating a wheres waldo web app. When creating the timer i have been able to get the timer working with the data in useRef, but i can not figure out how to update the div everytime the timer changes. Some help would be much appreciated.
Javascript:
const hour = useRef('00');
const second = useRef('00');
const stopTime = useRef(false);
const timerCycle = () => {
if (stopTime.current === false) {
second.current = parseInt(second.current);
minute.current = parseInt(minute.current);
hour.current = parseInt(hour.current)
second.current = second.current + 1;
if (second.current === 60) {
minute.current = minute.current + 1;
second.current = 0;
}
if (minute === 60) {
hour.current = hour.current + 1;
minute.current = 0;
second.current = 0;
}
if (second.current < 10 || second.current === 0) {
second.current = '0' + second.current;
}
if (minute.current < 10 || minute.current === 0) {
minute.current = '0' + minute.current;
}
if (hour.current < 10 || hour.current === 0) {
hour.current = '0' + hour.current;
}
console.log(second.current, minute.current, hour.current);
setTimeout(timerCycle, 1000);
}
}
JSX:
<div id="stopwatch">{hour.current}:{minute.current}:{second.current}</div>
We can take a look how different libraries do this:
From react-use
import { useReducer } from 'react';
const updateReducer = (num) => (num + 1) % 1_000_000;
export default function useUpdate() {
const [, update] = useReducer(updateReducer, 0);
return update;
}
Usage:
const update = useUpdate();
if (hour.current < 10 || hour.current === 0) {
hour.current = '0' + hour.current;
update()
}

Having issue resetting JS stopwatch

I made a little typing game that reveals some random text and you have to type the same in, so that you can test your typing speed. the users has the ability to play again and again, the issue is that when the user types play again, the stopwatch does not begin as it did the first time.
Can anyone help me with making the stopwatch restart everytime the user clicks on the play again button?
[ full code is here] (https://jsfiddle.net/kisho/ncbxd9o4/#&togetherjs=qD5bT8vLiw)
js portion-
const textDisplay = document.querySelector('#text-display');
const input = document.querySelector('#input');
const btn = document.querySelector('#btn');
const textBox = document.querySelector('#text-box');
const countdown = document.querySelector('#countdown');
const stopwatch = document.querySelector('#stopwatch');
const successMessege = document.querySelector('#success-messege');
const stopwatchTime = document.querySelector('#stopwatch-time');
btn.addEventListener('click', runGame);
function runGame() {
if ((btn.innerText = 'Play again')) {
playAgain();
fetchQuote();
countownTimer();
confirmQuote();
} else {
fetchQuote();
countownTimer();
confirmQuote();
}
}
function fetchQuote() {
fetch('https://api.quotable.io/random')
.then((res) => {
return res.json();
})
.then((data) => {
textDisplay.innerText = data.content;
});
}
function countownTimer() {
if (timer !== undefined) {
clearInterval(timer);
}
var timeleft = 2;
var downloadTimer = setInterval(function() {
if (timeleft <= 0) {
clearInterval(downloadTimer);
document.getElementById('countdown').innerHTML = 'Start Typing!';
input.classList.remove('displayNone');
runningStopwatch.classList.remove('displayNone');
begin();
} else {
document.getElementById('countdown').innerHTML = timeleft + ' seconds remaining';
}
timeleft -= 1;
}, 1000);
}
function confirmQuote() {
if ((countdown.innerHTML = 'Start typing!')) {
input.addEventListener('keyup', function(event) {
if (event.keyCode === 13) {
if (textDisplay.innerText === input.value) {
btn.innerText = 'Play again';
// textBox.classList.add('displayNone');
hold();
} else successMessege.innerText = 'Missed something there, try again!!';
}
});
}
}
function playAgain() {
textBox.classList.remove('displayNone');
input.classList.add('displayNone');
input;
input.value = '';
successMessege.innerText = '';
}
let ms = 0,
s = 0,
m = 0;
let timer;
let runningStopwatch = document.querySelector('.running-stopwatch');
function begin() {
timer = setInterval(run, 10);
}
function run() {
runningStopwatch.textContent =
(m < 10 ? '0' + m : m) + ': ' + (s < 10 ? '0' + s : s) + ': ' + (ms < 10 ? '0' + ms : ms);
ms++;
if (ms == 100) {
ms = 0;
s++;
}
if (s == 60) {
s = 0;
m++;
}
}
function hold() {
clearInterval(timer);
successMessege.innerText = `Nice job! You just typed in x seconds!`;
}
function stop() {
(ms = 0), (s = 0), (m = 0);
runningStopwatch.textContent =
(m < 10 ? '0' + m : m) + ': ' + (s < 10 ? '0' + s : s) + ': ' + (ms < 10 ? '0' + ms : ms);
}
You are not handling the clearInterval correctly.
You are clearing the interval only if one ends the game successfully.
My solution would be:
When calling the countownTimer() function, the first thing you should do, is to check if the interval timer is still running.
function countownTimer() {
if (timer !== undefined) {
clearInterval(timer);
}
// [...]
}
The next thing would be, to start the interval every time begin() gets called.
function begin() {
timer = setInterval(run, 10);
}

Won't let me set class name of a Javascript created div

I'm using a function to create a div element on the page. I want to assign a className but I get the error: cannot set property className of undefined.
But I did this in another function and it worked. Why is this one not working?
If I failed to provide the code relevant to the problem I apologize. I'm in a rush and included code that I thought might be relevant in order of relevancy.
** WORKING FUNCTION **
function makeBomb() {
if (player.ready && (player.hasBomb < player.maxBombs)) {
player.score -= 300;
player.hasBomb++;
player.bomb = document.createElement('div');
player.bomb.className = 'bomb'; //DOESN'T THROW ERROR ----
gameArea.appendChild(player.bomb);
player.bomb.x = player.x;
player.bomb.y = player.y;
player.bomb.style.left = player.bomb.x + 'px';
player.bomb.style.top = player.bomb.y + 'px';
player.ready = false;
setTimeout(function () {
player.ready = true;
}, 1000);
}
}
** NOT WORKING FUNCTION **
function makeBullet() {
if (player.enemy.bulletCount < player.enemy.maxBulletCount &&
player.enemy.bulletInterval == true)
player.enemy.bullet = document.createElement('div');
player.enemy.bullet.className = 'bullet'; //THROWS ERROR -----
gameArea.appendChild(player.enemy.bullet);
player.enemy.bullet.x = player.enemy.x;
player.enemy.bullet.y = player.enemy.y;
player.enemy.bullet.style.left = player.enemy.bullet.x +
(player.enemy.offsetWidth / 3) + 'px';
player.enemy.bullet.style.top = player.enemy.bullet.y +
(player.enemy.offsetHeight / 4) + 'px';
player.enemy.bulletCount++;
player.enemy.bulletInterval = false;
setInterval(function(){
player.enemy.bulletInterval = true;
}, 4000);
}
** STARTING CODE THAT MIGHT HAVE CONTEXT IDK**
function start() {
if (player.games === 1) {
gameArea.removeChild(finalScore);
}
gameMessage.style.display = 'none';
score.style.display = "inline-block";
scoreArea.style.display = "inline-block";
text.style.display = "inline-block";
player.inplay = true;
makeEnemy();
player.plane = document.createElement("div");
player.plane.setAttribute("class", "plane");
gameArea.appendChild(player.plane);
player.enemy.x = player.enemy.offsetLeft;
player.enemy.y = player.enemy.offsetTop;
player.x = player.plane.offsetLeft;
player.y = player.plane.offsetTop;
window.requestAnimationFrame(playGame);
}
** OTHER CODE THAT MIGHT HAVE CONTEXT **
function makeEnemy() {
player.enemy = document.createElement('div');
player.enemy.className = 'enemy';
player.enemy.style.left = Math.floor(Math.random() * .
gameArea.offsetWidth - 300) + 100 + 'px';
gameArea.appendChild(player.enemy);
player.enemy.x = player.enemy.offsetLeft;
}
** JUST IN CASE YOU NEED -- idk its hard for me to keep track of everything that might be related to the problem... sorry.. **
title.addEventListener("click", changeColor);
const gameArea = document.querySelector(".gameArea");
const game = document.querySelector(".game");
const scoreArea = document.querySelector(".scoreArea");
const score = document.querySelector(".score");
const text = document.querySelector(".text");
document.addEventListener('keydown', pressOn);
document.addEventListener('keyup', pressOff);
gameMessage.addEventListener('click', start);
let player = {
score: 2000,
speed: 5,
inplay: false,
ready: true,
maxBombs: 4,
hasBomb: 0,
hit: 0,
hitMax: 9,
games: 0,
enemy: {
x: 0
},
getHit: 0,
getHitMax: 20,
swing: false
}
let keys = {
space: false
}
** FULL JS FILE: BE WARNED IM VERY NEW AND THIS IS NOT GOOD CODE **
const title = document.querySelector(".title");
const gameMessage = document.querySelector(".gameMessage");
function changeColor() {
let newArray = ["darksalmon", "lightsalmon", "crimson", "red", "deeppink", "yellowgreen", "ghostwhite"];
let random = Math.floor(Math.random() * Math.floor(newArray.length - 1));
if (title.style.color != newArray[random]) {
title.style.color = newArray[random];
console.log(title.style.color);
} else {
changeColor();
}
}
title.addEventListener("click", changeColor);
const gameArea = document.querySelector(".gameArea");
const game = document.querySelector(".game");
const scoreArea = document.querySelector(".scoreArea");
const score = document.querySelector(".score");
const text = document.querySelector(".text");
document.addEventListener('keydown', pressOn);
document.addEventListener('keyup', pressOff);
gameMessage.addEventListener('click', start);
let player = {
score: 2000,
speed: 5,
inplay: false,
ready: true,
maxBombs: 4,
hasBomb: 0,
hit: 0,
hitMax: 9,
games: 0,
enemy: {
x: 0
},
getHit: 0,
getHitMax: 20,
swing: false
}
let keys = {
space: false
}
function start() {
if (player.games === 1) {
gameArea.removeChild(finalScore);
}
gameMessage.style.display = 'none';
score.style.display = "inline-block";
scoreArea.style.display = "inline-block";
text.style.display = "inline-block";
player.inplay = true;
makeEnemy();
player.plane = document.createElement("div");
player.plane.setAttribute("class", "plane");
gameArea.appendChild(player.plane);
player.enemy.x = player.enemy.offsetLeft;
player.enemy.y = player.enemy.offsetTop;
player.x = player.plane.offsetLeft;
player.y = player.plane.offsetTop;
window.requestAnimationFrame(playGame);
}
function playGame() {
if (player.inplay) {
moveBomb();
if(player.x < (gameArea.offsetWidth / 2)) {
console.log('WORKED');
makeBullet();
}
if (player.swing){
player.plane.style.backgroundImage ='url(guts1.png)';
player.swing = false;
//player.plane.style.width = 210 + 'px';
}
if (keys['x'] && player.enemy && isCollide(player.plane, player.enemy)) {
removeEnemy();
}
if (player.enemy) {
if (isCollide(player.plane, player.enemy)) {
player.getHit++;
if (player.getHit > player.getHitMax){
endGame();
}
} else {
player.getHit = 0;
}
if (player.x > player.enemy.x) {
player.enemy.x += 1;
}
if (player.x < player.enemy.x) {
player.enemy.x -= 1;
}
player.enemy.style.left = player.enemy.x + 'px';
}
if (player.hasBomb >= player.maxBombs && player.bomb.y > gameArea.offsetHeight - 20) {
endGame();
}
if (keys.space) {
makeBomb()
}
if (keys.ArrowUp && player.y > 0) {
player.y -= (player.speed + (player.speed * .5));
}
if (keys.ArrowDown && player.y < (gameArea.offsetHeight - player.plane.offsetHeight - 30)) {
player.y += (player.speed + (player.speed * .5));
}
if (keys.ArrowLeft && player.x > 0) {
player.x -= (player.speed + (player.speed * .5));
}
if (keys.ArrowRight && player.x < (gameArea.offsetWidth)) {
player.x += (player.speed - (player.speed * .5));
}
if (player.x == (gameArea.offsetWidth)) {
player.x = 0;
player.score -= 100;
if (!player.enemy) {
makeEnemy();
}
}
player.score -= .4;
if (player.score < 0) {
player.score = 0;
}
player.x += (player.speed * .5);
score.innerHTML = Math.floor(player.score) + ' Bombs left: ' + (player.maxBombs - player.hasBomb);
player.plane.style.left = player.x + 'px';
player.plane.style.top = player.y + 'px';
window.requestAnimationFrame(playGame);
}
}
function pressOn(e) {
e.preventDefault();
let tempKey = (e.key == " ") ? "space" : e.key;
keys[tempKey] = true;
if (keys['x'] && player.swing == false){
playerPlane = player.plane;
player.plane.style.backgroundImage ='url(guts2.png)';
setTimeout(function () {
player.swing = true;
}, 300);
//player.plane.style.width = 400 + 'px';
}
console.log(tempKey)
console.log(keys);
}
function pressOff(e) {
e.preventDefault();
let tempKey = (e.key== " ") ? "space" : e.key;
console.log(tempKey);
// if (keys['x'] && player.swing){
// playerPlane = player.plane;
// player.plane.style.backgroundImage ='url(guts1.png)';
// player.swing = false;
// //player.plane.style.width = 210 + 'px';
//
// }
if (keys['space'] || keys['x']) {
keys['space'] = 0;
keys['x'] = 0;
}
keys[tempKey] = false;
console.log(keys);
}
function moveBomb() {
let bombs = document.querySelectorAll('.bomb');
bombs.forEach(function (item) {
item.y += 10;
item.style.top = item.y + 'px';
if (item.y > gameArea.offsetHeight) {
item.parentNode.removeChild(item);
player.bomb = null;
}
if (player.enemy && player.bomb) {
if (isCollide(item, player.enemy)) {
player.hit++;
}
}
if (player.hit > player.hitMax) {
item.parentNode.removeChild(item);
player.bomb = null;
player.score += 2000;
player.hit = 0;
player.hasBomb -= 2
gameArea.removeChild(player.enemy);
player.enemy = null;
}
})
}
function makeEnemy() {
player.enemy = document.createElement('div');
player.enemy.className = 'enemy';
player.enemy.style.left = Math.floor(Math.random() * gameArea.offsetWidth - 300) + 100 + 'px';
gameArea.appendChild(player.enemy);
player.enemy.x = player.enemy.offsetLeft;
}
//function getLocationX(a){
// let aRect = a.getBoundingClientRect();
// let aX = aRect.x;
// return aX;
// //w console.log(aX);
//}
//
//function getLocationY(a){
// let aRect = a.getBoundingClientRect();
// let aY = aRect.y;
// return aY;
// // console.log(aY);
//}
function isCollide(a, b) {
let aRect = a.getBoundingClientRect();
let bRect = b.getBoundingClientRect();
return !(
(aRect.bottom < bRect.top) ||
(aRect.top > bRect.bottom) ||
(aRect.right < bRect.left) ||
(aRect.left > bRect.right)
)
}
function makeBomb() {
if (player.ready && (player.hasBomb < player.maxBombs)) {
player.score -= 300;
player.hasBomb++;
player.bomb = document.createElement('div');
player.bomb.className = 'bomb';
gameArea.appendChild(player.bomb);
player.bomb.x = player.x;
player.bomb.y = player.y;
player.bomb.style.left = player.bomb.x + 'px';
player.bomb.style.top = player.bomb.y + 'px';
player.ready = false;
setTimeout(function () {
player.ready = true;
}, 1000);
}
}
function makeBullet() {
if (player.enemy.bulletCount < player.enemy.maxBulletCount && player.enemy.bulletInterval == true)
player.enemy.bullet = document.createElement('div');
player.enemy.bullet.className = 'bullet';
gameArea.appendChild(player.enemy.bullet);
player.enemy.bullet.x = player.enemy.x;
player.enemy.bullet.y = player.enemy.y;
player.enemy.bullet.style.left = player.enemy.bullet.x + (player.enemy.offsetWidth / 3) + 'px';
player.enemy.bullet.style.top = player.enemy.bullet.y + (player.enemy.offsetHeight / 4) + 'px';
player.enemy.bulletCount++;
player.enemy.bulletInterval = false;
setInterval(function(){
player.enemy.bulletInterval = true;
}, 4000);
}
function endGame() {
if (player.enemy) {
gameArea.removeChild(player.enemy);
}
gameArea.removeChild(player.plane);
if (player.bomb){
gameArea.removeChild(player.bomb);
player.bomb = null;
}
score.style.display = 'none';
scoreArea.style.display = 'none';
text.style.display = 'none';
gameMessage.style.display = 'inline-block';
player.inplay = false;
player.hasBomb = 0;
finalScore = document.createElement('div');
finalScore.classList.add('finalScore');
finalScore.innerHTML = 'YOU SCORED: ' + Math.floor(player.score);
gameArea.appendChild(finalScore);
player.games = 1;
player.getHit = 0;
}
function removeEnemy() {
gameArea.removeChild(player.enemy);
player.enemy = null;
player.score += 2000;
}
function makeBullet() {
if (player.enemy.bulletCount < player.enemy.maxBulletCount &&
player.enemy.bulletInterval == true)
youre missing curly braces at the end of the if statement and i think its interpretting the next line as a part single line if statement
change to
function makeBullet() {
if (player.enemy.bulletCount < player.enemy.maxBulletCount &&
player.enemy.bulletInterval == true) {
...
...
...
}
}

JavaScript timer in my program stops in unpredictable way

I'm a completely beginner and I write code in my free time. Can anyone explain me please why sometimes my Pomodore Clock is stuck when it hits 0 0 1. (hours, minutes, seconds)
I can start it in one tab in chrome and it will work for unpredictable amount of cycles and then for no reason it will stop at 0 0 1, just before starting next cycle. I want it to work continuous (work, break, work, break, etc.) until I hit reset button...
Is there better way to handle time in JS?
Code:
// Code wrapped in a closure to avoid global variables
(function () {
let countdown;
let timeIsRunnig = false;
let actionTypeSwitch = "Work";
const timerDisplay = document.querySelector(".display__time-left");
const infoDisplay = document.querySelector(".display__info");
const endTime = document.querySelector(".display__end-time");
const buttons = document.querySelectorAll("[data-time]");
const breakSettings = document.querySelectorAll(".settings__breakButton");
const workSettings = document.querySelectorAll(".settings__workButton");
const breakValue = document.querySelector("#valueBreak");
const workValue = document.querySelector("#valueWork");
const buttonMain = document.querySelector("#buttonMain");
let workValueSettings = 25; // Default work session value in min
let breakValueSettings = 5; // Default break session value in min
workValue.textContent = workValueSettings + ' min';
breakValue.textContent = breakValueSettings + ' min';
timerDisplay.textContent = `${ workValueSettings}:00`;
infoDisplay.textContent = "Are you ready?";
endTime.textContent = "Press START";
function timer(seconds) {
// Clear any existing timers
clearInterval(countdown);
// Current time in ms
const now = Date.now();
const future = now + seconds * 1000;
displayTimeLeft(seconds);
displayEndTime(future);
function timeCalc() {
const secondsLeft = Math.round((future - Date.now()) / 1000);
// Check if we should stop it
if (secondsLeft < 0) {
clearInterval(countdown);
return;
}
// Display it
displayTimeLeft(secondsLeft);
}
countdown = setInterval(timeCalc, 1000);
}
function startTimer() {
const seconds = workValueSettings * 60;
actionTypeSwitch = "Work";
infoDisplay.textContent = "Working hard!";
timer(seconds);
}
function startBreak() {
const seconds = breakValueSettings * 60;
actionTypeSwitch = "Break";
infoDisplay.textContent = "Short break!";
timer(seconds);
}
function resetTimer() {
const seconds = workValueSettings * 60;
// Clear any existing timers
clearInterval(countdown);
// Refresh display
displayTimeLeft(seconds);
infoDisplay.textContent = "Are you ready?";
endTime.textContent = "Press START";
}
function startAndReset() {
let name = "START";
if (timeIsRunnig === false) {
timeIsRunnig = true;
name = "RESET";
this.innerHTML = name;
startTimer();
} else {
timeIsRunnig = false;
name = "START";
this.innerHTML = name;
resetTimer();
}
}
function playSoundStartBreak() {
// Returns the first Element within the document
// that matches the specified group of selectors.
const audio = document.querySelector(`audio[data-sound="workDone"]`);
if(!audio) return; // Stop the function from running
audio.currentTime = 0; // Rewind to the start
audio.play();
}
function playSoundBackToWork() {
// Returns the first Element within the document
// that matches the specified group of selectors.
const audio = document.querySelector(`audio[data-sound="backToWork"]`);
if(!audio) return; // Stop the function from running
audio.currentTime = 0; // Rewind to the start
audio.play();
}
function displayTimeLeft(sec) {
const hours = parseFloat(Math.floor(sec / 3600));
const minutes = parseFloat(Math.floor(sec / 60));
const remainderMinutes = parseFloat(minutes % 60);
const remainderSeconds = parseFloat(sec % 60);
console.log(hours, remainderMinutes, remainderSeconds);
// Play sound when timer gets to 0
if (parseFloat(sec) === 0) {
if (actionTypeSwitch === "Work") {
playSoundStartBreak()
startBreak();
} else {
playSoundBackToWork();
startTimer();
}
}
// Hide hours when hours is 0
let hoursFirstStatement = hours < 10 ? "0" : "";
let hoursSecondStatement = hours;
let colon = ":";
if (hours === 0) {
hoursFirstStatement = "";
hoursSecondStatement = "";
colon = "";
}
// This `${}` allows adding javascript variables in strings
const display = `${hoursFirstStatement}${hoursSecondStatement}${colon}${
remainderMinutes < 10 ? "0" : ""}${remainderMinutes}:${
remainderSeconds < 10 ? "0" : ""}${remainderSeconds}`;
timerDisplay.textContent = display;
document.title = display + " " + "(" + actionTypeSwitch + ")";
}
function displayEndTime(timestamp) {
const end = new Date(timestamp);
const hours = end.getHours();
const minutes = end.getMinutes();
endTime.textContent = `This session ends at ${hours < 10 ? "0" : ""}${hours}:${
minutes < 10 ? "0" : ""}${minutes}`;
}
function changeBreakSettings() {
const breakChangeValue = parseInt(this.dataset.settings);
if ((breakValueSettings <= 1 && breakChangeValue === -1) ||
(breakValueSettings >= 30 && breakChangeValue === 1)) {
return; // Do nothing when this conditions are fulfilled
} else {
breakValueSettings = breakValueSettings + breakChangeValue;
breakValue.textContent = breakValueSettings + ' min';
}
}
function changeWorkSettings() {
const workChangeValue = parseInt(this.dataset.settings);
if ((workValueSettings <= 5 && workChangeValue === -1) ||
(workValueSettings >= 120 && workChangeValue === 1)) {
return; // Do nothing when this conditions are fulfilled
} else {
workValueSettings = workValueSettings + workChangeValue;
workValue.textContent = workValueSettings + ' min';
}
}
breakSettings.forEach(button => button.addEventListener("click", changeBreakSettings));
workSettings.forEach(button => button.addEventListener("click", changeWorkSettings));
buttonMain.addEventListener("click", startAndReset);
}());
You need to do clearInterval() against timeCalc & update the display on the case of secondsLeft < 0. Because when you do not clear it, when it is showing "1 second left", the call of timeCalc will goes into the if statement and return, and never update the display and timeCalc is never clear and you get into infinite loop.

Categories