Reset counter on spacebar and onclick - javascript

I'm trying to make a count-down that counts down from 200 to 0 in steps of 10.
This timer can be stopped and should then be reset to 200, however, I need also the value of the moment is stopped. The countdown fills the div #log with innerHTML. Whenever I "stop" the timer, I take the value of #log and place it in #price and I hide #log. The problem here is that the timer continues in the background, while I want it to reset so it can be started again by clicking on start. However, it just continues counting down and only after it's done, I can start it again.
In the example, it doesn't take so long for it to reach 0, but in the end, it'll take 15-20 seconds to reach 0, which'll be too long to wait for.
So in short: Countdown 200-0, but on click of Start-button or spacebar, it should stop the function running at the moment, so it can be started again.
See this PEN
If you have any suggestions on how to approach it completely different, you're very welcome to share!
HTML
<button id="btn" class="normal">Start</button>
<div id="log">#</div>
<div id="price"></div>
JS
var log = document.getElementById("log");
var btn = document.getElementById("btn");
var price = document.getElementById("price");
var counting = false;
var btnClassName = btn.getAttribute("class");
function start(count) {
if (!counting) {
counting = true;
log.innerHTML = count;
var timer = setInterval(function() {
if (count >= 0) {
log.innerHTML = count;
count -= 10;
} else {
clearInterval(timer);
count = arguments[0];
counting = false;
btn.className = "normal";
}
}, 150);
};
};
btn.onclick = function() {
if (btnClassName == "normal") {
start(200);
price.style.display = 'none';
log.style.display = 'block';
btn.className = "counting";
log.innerHTML = "";
} else {
}
};
document.body.onkeyup = function(e){
if(e.keyCode == 32){
price.innerHTML = log.innerHTML;
price.style.display = 'block';
log.style.display = 'none';
}
}

I "re-code" your code because there are several issues there.
Just read the code and tell me if that's you are looking for or if you have any questions..
var log = document.getElementById("log");
var btn = document.getElementById("btn");
var price = document.getElementById("price");
var counting = false;
var timer;
var c = 0;
function start(count) {
btn.blur();
if (!counting) {
c = count;
counting = true;
log.innerHTML = count;
timer = setInterval(tick, 1500);
tick();
};
};
function tick() {
if (c >= 0) {
log.innerHTML = c;
c -= 10;
}
else {
clearInterval(timer);
c = arguments[0];
counting = false;
btn.className = "normal";
}
}
btn.onclick = function() {
resetTimer();
var btnClassName = btn.getAttribute("class");
if (btnClassName == "normal") {
price.style.display = 'none';
log.style.display = 'block';
btn.className = "counting";
log.innerHTML = "";
start(200);
} else {
pause();
}
};
document.body.onkeyup = function(e) {
if(e.keyCode == 32) {
e.preventDefault();
pause();
}
}
function pause() {
resetTimer();
price.innerHTML = log.innerHTML;
price.style.display = 'block';
log.style.display = 'none';
btn.className = 'normal';
counting = false;
}
function resetTimer() {
clearInterval(timer);
}
body { font: 100% "Helvetica Neue", sans-serif; text-align: center; }
/*#outer {
width: 400px;
height: 400px;
border-radius: 100%;
background: #ced899;
margin: auto;
}
#inner {
width: 350px;
height: 350px;
border-radius: 100%;
background: #398dba;
margin: auto;
}*/
#log, #price {
font-size: 500%;
font-weight: bold;
}
<div id="outer">
<div id="inner">
<div id="arrow">
</div>
</div>
</div>
<button id="btn" class="normal">Start</button>
<div id="log">#</div>
<div id="price"></div>

Though you have already got your answer, you can try something like this:
Also I have taken liberty to reformat your code, and for demonstration purpose, have kept delay for interval as 1000
JSFiddle
function Counter(obj) {
var _initialVaue = obj.initialValue || 0;
var _interval = null;
var status = "Stopped";
var start = function() {
this.status = "Started";
if (!_interval) {
_interval = setInterval(obj.callback, obj.delay);
}
}
var reset = function() {
stop();
start();
}
var stop = function() {
if (_interval) {
this.status = "Stopped";
window.clearInterval(_interval);
_interval = null;
}
}
return {
start: start,
reset: reset,
stop: stop,
status: status
}
}
function init() {
var counterOption = {}
var count = 200;
counterOption.callback = function() {
if (count >= 0) {
printLog(count);
count -= 10;
} else {
counter.stop();
}
};
counterOption.delay = 1000;
counterOption.initialValue = 200
var counter = new Counter(counterOption);
function registerEvents() {
document.getElementById("btn").onclick = function() {
if (counter.status === "Stopped") {
count = counterOption.initialValue;
counter.start();
printLog("")
toggleDivs(counter.status)
}
};
document.onkeyup = function(e) {
if (e.keyCode === 32) {
printLog(counterOption.initialValue);
counter.stop();
toggleDivs(counter.status)
printPrice(count);
}
}
}
function printLog(str) {
document.getElementById("log").innerHTML = str;
}
function printPrice(str) {
document.getElementById("price").innerHTML = str;
}
function toggleDivs(status) {
document.getElementById("log").className = "";
document.getElementById("price").className = "";
var hideID = (status === "Started") ? "price" : "log";
document.getElementById(hideID).className = "hide";
}
registerEvents();
}
init();
body {
font: 100% "Helvetica Neue", sans-serif;
text-align: center;
}
.hide{
display: none;
}
#log,
#price {
font-size: 500%;
font-weight: bold;
}
<div id="outer">
<div id="inner">
<div id="arrow">
</div>
</div>
</div>
<button id="btn" class="normal">Start</button>
<div id="log">#</div>
<div id="price"></div>
Hope it helps!

Related

How to remove an event listener and add the listener back on another element click

I am creating a simple picture matching game and I will love to make sure when the picture is clicked once, the event listener is removed, this will help me stop the user from clicking on the same image twice to get a win, and then when the user clicks on another element the listener should be added back, I tried doing this with an if statement but the listener is only removed and never added back, I decided to reload the page which somehow makes it look like a solution but I need a better solution that can help me not to reload the page but add the listener back so that the element can be clicked again after the last else if statement run.
here is the sample code below.
//Selecting query elements
const aniSpace = document.querySelector(".container");
const firstCard = document.querySelector("#fstcard");
const secondCard = document.querySelector("#sndcard");
const thirdCard = document.querySelector("#thrdcard");
const playGame = document.querySelector('#play');
const scores = document.querySelector('.scoreboard');
count = 0;
var firstIsClicked = false;
var isCat = false;
var isElephant = false;
var isDog = false;
var isButterfly = false;
var isEmpty = false;
const animatchApp = () => {
const animals = {
cat: {
image: "asset/images/cat.png",
name: "Cat"
},
dog: {
image: "asset/images/puppy.png",
name: "Dog"
},
elephant: {
image: "asset/images/elephant.png",
name: "Elephant"
},
butterfly: {
image: "asset/images/butterfly.png",
name: "butterfly"
}
}
var score = 0;
firstCard.addEventListener('click', function firstBtn() {
var type = animals.cat.name;
if (firstIsClicked === true && isCat === true) {
firstCard.innerHTML = `<img src="${animals.cat.image}">`;
firstCard.classList.add('display');
alert("You won");
score = score + 50;
console.log(score);
document.getElementById('scores').innerHTML = score;
firstIsClicked = false;
isElephant = false;
if (score >= 200){
alert("You are unstoppable, Game won.");
count = 0;
score = 0;
document.getElementById('scores').innerHTML = score;
document.getElementById('attempts').innerHTML = count;
}
firstCard.removeEventListener('click', firstBtn);
} else if (firstIsClicked === false) {
firstCard.innerHTML = `<img src="${animals.cat.image}">`;
firstCard.classList.add('display');
firstIsClicked = true;
isCat = true;
firstCard.removeEventListener('click', firstBtn);
} else if (firstIsClicked === true && isCat != true) {
alert("Not Matched");
count++;
document.getElementById('attempts').innerHTML = count;
firstCard.innerHTML = '';
secondCard.innerHTML = '';
thirdCard.innerHTML = '';
firstCard.classList.remove('display');
secondCard.classList.remove('display');
thirdCard.classList.remove('display');
firstIsClicked = false;
isCat = false;
isDog = false;
isElephant = false;
isButterfly = false;
score = 0;
document.getElementById('scores').innerHTML = score;
location.reload(true);
}
})
secondCard.addEventListener('click', function secondBtn() {
var type = animals.elephant.name;
if (firstIsClicked === true && isElephant === true) {
secondCard.innerHTML = `<img src="${animals.elephant.image}">`;
secondCard.classList.add('display');
alert("You won");
score = score + 50;
console.log(score);
document.getElementById('scores').innerHTML = score;
firstIsClicked = false;
isElephant = false;
if (score >= 200){
alert("You are unstoppable, Game won.");
count = 0;
score = 0;
document.getElementById('scores').innerHTML = score;
document.getElementById('attempts').innerHTML = count;
}
secondCard.removeEventListener('click', secondBtn);
} else if (firstIsClicked === false) {
secondCard.innerHTML = `<img src="${animals.elephant.image}">`;
secondCard.classList.add('display');
firstIsClicked = true;
isElephant = true;
secondCard.removeEventListener('click', secondBtn);
} else if (firstIsClicked === true && isElephant != true) {
alert("Not Matched");
count++;
document.getElementById('attempts').innerHTML = count;
firstCard.innerHTML = '';
secondCard.innerHTML = '';
thirdCard.innerHTML = '';
firstCard.classList.remove('display');
secondCard.classList.remove('display');
thirdCard.classList.remove('display');
firstIsClicked = false;
isCat = false;
isDog = false;
isElephant = false;
isButterfly = false;
score = 0;
document.getElementById('scores').innerHTML = score;
location.reload(true);
}
})
thirdCard.addEventListener('click', function thirdBtn() {
var type = animals.dog.name;
if (firstIsClicked === true && isDog === true) {
thirdCard.innerHTML = `<img src="${animals.dog.image}">`;
thirdCard.classList.add('display');
alert("You won");
score = score + 50;
console.log(score);
document.getElementById('scores').innerHTML = score;
firstIsClicked = false;
isDog = false;
if (score >= 200){
alert("You are unstoppable, Game won.");
count = 0;
score = 0;
document.getElementById('scores').innerHTML = score;
document.getElementById('attempts').innerHTML = count;
}
thirdCard.removeEventListener('click', thirdBtn);
} else if (firstIsClicked === false) {
thirdCard.innerHTML = `<img src="${animals.dog.image}">`;
thirdCard.classList.add('display');
firstIsClicked = true;
isDog = true;
thirdCard.removeEventListener('click', thirdBtn);
} else if (firstIsClicked === true && isDog != true) {
alert("Not Matched");
count++;
document.getElementById('attempts').innerHTML = count;
firstCard.innerHTML = '';
secondCard.innerHTML = '';
thirdCard.innerHTML = '';
firstCard.classList.remove('display');
secondCard.classList.remove('display');
thirdCard.classList.remove('display');
firstIsClicked = false;
isCat = false;
isDog = false;
isElephant = false;
isButterfly = false;
score = 0;
document.getElementById('scores').innerHTML = score;
location.reload(true);
}
})
document.getElementById('attempts').innerHTML = count;
}
animatchApp();
.h1 {
text-align: center;
background-color: azure;
background-image: url("");
}
* {
box-sizing: border-box;
}
.container {
width: 500px;
}
.card1 {
background-color: blue;
float: left;
width: 30%;
padding: 10px;
height: 150px; /* Should be removed. Only for demonstration */
border: 1px solid rgb(179, 177, 177);
transition: transform 0.8s;
transform-style: preserve-3d;
}
.card2 {
background-color: blue;
float: left;
width: 30%;
padding: 10px;
height: 150px; /* Should be removed. Only for demonstration */
border: 1px solid rgb(179, 177, 177);
transition: transform 0.8s;
transform-style: preserve-3d;}
.card3 {
background-color: blue;
float: left;
width: 30%;
padding: 10px;
height: 150px; /* Should be removed. Only for demonstration */
border: 1px solid rgb(179, 177, 177);
transition: transform 0.8s;
transform-style: preserve-3d;
}
.scoreboard {
float: left;
width: 100%;
padding: 10px;
height: 150px; /* Should be removed. Only for demonstration */
}
img {
width: 100%;
height: 100%;
background-color: white;
}
.display {
background-color: white;
transform: rotateY(180deg);
}
<div class="container">
<h1 class="h1">Animatch</h1>
<div class="first">
<div class="card1" id="fstcard"></div>
<div class="card1" id="sndcard"></div>
<div class="card1" id="thrdcard"></div>
</div>
</div>
<div class="scoreboard">
<p>
<button id="play" onclick="animatchApp()">Play</button>
<br>
Score: <span id="scores">0</span>
<br>
Failed attempts: <span id="attempts"></span>
</p>
</div>
you have to define function outside of onclick because you will need this function reference to remove or add it to eventlistener later
see a example below
function onload(){
var main = document.querySelector(".main"),
btns = main.querySelectorAll(".buttons input"),
box = main.querySelector(".box")
btns[0].addEventListener("click",function(){
box.addEventListener("click",functionForEvent)
})
btns[1].addEventListener("click",function(){
box.removeEventListener("click",functionForEvent)
})
function functionForEvent(e){
console.log("clicked")
}
}
onload()
<div class="main">
<div class="box" style="height:120px;width:120px;border:1px solid black;">Click Me</div>
<div class="buttons">
<input type="button" value="Add Event">
<input type="button" value="Remove Event">
</div>
</div>
Here is an example, that shows how to remove the click event from the item clicked and add it to the other items.
It colors the items that can be clicked green, and the item that can't be clicked red.
To keep the example short, it doesn't check, if the elements it operates on, are well defined.
function myonload() {
let elems = document.querySelectorAll('.mydiv');
for(let i = 0; i < elems.length; ++i) {
let elem = elems[i];
elem.addEventListener('click', mydiv_clicked);
}
}
function mydiv_clicked(e) {
let elems = document.querySelectorAll('.mydiv');
for(let i = 0; i < elems.length; ++i) {
let elem = elems[i];
if(elem == e.target) {
elem.removeEventListener('click', mydiv_clicked);
elem.classList.add('mycolor_clicked');
elem.classList.remove('mycolor');
// Do additional logic here
} else {
elem.addEventListener('click', mydiv_clicked);
elem.classList.remove('mycolor_clicked');
elem.classList.add('mycolor');
// Do additional logic here
}
}
}
.mydiv {
height:30px;
width: 200px;
border:1px solid black;
margin-bottom:2px;
}
.mycolor {
background-color:#00ff00;
}
.mycolor_clicked {
background-color:#ff0000;
}
<body onload="myonload()">
<div class="mydiv mycolor">First area</div>
<div class="mydiv mycolor">Second area</div>
<div class="mydiv mycolor">Third area</div>
</body>
The example shown here does not need to check if an event handler already exists, as adding the same event handler twice, replaces the existing one.
You could also add a custom attribute to your elements and toggle it, instead of adding and removing event listeners as shown here and name your attribute data-something, for example data-can-be-clicked.

Cant figure out how to implement a 3 strike feature in Javascript game

I need to allow the user to make 2 mistakes before they lose the game. I need to:
-Create a global variable to track the number of mistakes
-Initialize that variable during startGame
-Edit the guess function so that it updates the mistake counter when the user makes and mistake, and adds a check of that variable before calling the loseGame function
Im having trouble implementing this into the JS file. How can I do it?
JS File:
const cluePauseTime = 333; //how long to pause in between clues
const nextClueWaitTime = 1000; //how long to wait before starting playback of the clue sequence
//Global variables
var clueHoldTime = 200; //how long to hold each clue's light/sound
// var pattern = [2, 3, 1, 4, 6, 1, 2, 4, 3, 5];
var pattern = [];
var clueLength = 10;
///////////////////////////////
var progress = 0;
var gamePlaying = false;
var tonePlaying = false;
var volume = 0.5;
var guessCounter = 0;
function startGame() {
progress = 0;
pattern = []; // reset so array doesn't get longer then 10 if we restart game
for (var i = 0; i < clueLength; i++) {
pattern.push(getRandomInt(5));
}
console.log("pattern: " + pattern);
gamePlaying = true;
document.getElementById("startBtn").classList.add("hidden");
document.getElementById("stopBtn").classList.remove("hidden");
playClueSequence();
}
function stopGame() {
gamePlaying = false;
document.getElementById("startBtn").classList.remove("hidden");
document.getElementById("stopBtn").classList.add("hidden");
}
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max) + 1);
}
function lightButton(btn) {
document.getElementById("button" + btn).classList.add("lit");
}
function clearButton(btn) {
document.getElementById("button" + btn).classList.remove("lit");
}
function playSingleClue(btn) {
if (gamePlaying) {
lightButton(btn);
playTone(btn, clueHoldTime);
setTimeout(clearButton, clueHoldTime, btn);
}
}
function playClueSequence() {
guessCounter = 0;
let delay = nextClueWaitTime; //set delay to initial wait time
for (let i = 0; i <= progress; i++) {
// for each clue that is revealed so far
console.log("play single clue: " + pattern[i] + " in " + delay + "ms");
setTimeout(playSingleClue, delay, pattern[i]); // set a timeout to play that clue
delay += clueHoldTime;
delay += cluePauseTime;
}
}
function loseGame() {
stopGame();
alert("Game Over. You lost.");
}
function winGame() {
stopGame();
alert("Yayyyyy, you win!!");
}
function guess(btn) {
console.log("user guessed: " + btn);
if (!gamePlaying) {
return;
}
if (pattern[guessCounter] == btn) {
if (guessCounter == progress) {
if (progress == pattern.length - 1) {
winGame();
} else {
progress++;
playClueSequence();
}
} else {
guessCounter++;
}
//guessCounter++;
} else {
loseGame();
}
}
// Sound Synthesis Functions
const freqMap = {
1: 261.6,
2: 329.6,
3: 392,
4: 466.2,
5: 432.8,
6: 336.2
};
function playTone(btn, len) {
o.frequency.value = freqMap[btn];
g.gain.setTargetAtTime(volume, context.currentTime + 0.05, 0.025);
tonePlaying = true;
setTimeout(function() {
stopTone();
}, len);
}
function startTone(btn) {
if (!tonePlaying) {
o.frequency.value = freqMap[btn];
g.gain.setTargetAtTime(volume, context.currentTime + 0.05, 0.025);
tonePlaying = true;
}
}
function stopTone() {
g.gain.setTargetAtTime(0, context.currentTime + 0.05, 0.025);
tonePlaying = false;
}
//Page Initialization
// Init Sound Synthesizer
var context = new AudioContext();
var o = context.createOscillator();
var g = context.createGain();
g.connect(context.destination);
g.gain.setValueAtTime(0, context.currentTime);
o.connect(g);
o.start(0);
HTML:
<!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" />
<title>Hello!</title>
<!-- import the webpage's stylesheet -->
<link rel="stylesheet" href="/style.css" />
<!-- import the webpage's javascript file -->
<script src="/script.js" defer></script>
</head>
<body>
<h1>Memory Game</h1>
<p>
Welcome to the game that will test your memory!
</p>
<button id="startBtn" onclick="startGame()">
Start
</button>
<button id="stopBtn" class="hidden" onclick="stopGame()">
Stop
</button>
<div id="gameButtonArea">
<button
id="button1"
onclick="guess(1)"
onmousedown="startTone(1)"
onmouseup="stopTone()"
></button>
<button
id="button2"
onclick="guess(2)"
onmousedown="startTone(2)"
onmouseup="stopTone()"
></button>
<button
id="button3"
onclick="guess(3)"
onmousedown="startTone(3)"
onmouseup="stopTone()"
></button>
<button
id="button4"
onclick="guess(4)"
onmousedown="startTone(4)"
onmouseup="stopTone()"
></button>
<button
id="button5"
onclick="guess(5)"
onmousedown="startTone(5)"
onmouseup="stopTone()"
></button>
<button
id="button6"
onclick="guess(6)"
onmousedown="startTone(6)"
onmouseup="stopTone()"
></button>
</div>
</body>
</html>
CSS:
body {
font-family: helvetica, arial, sans-serif;
margin: 2em;
background-color: slategrey;
color: white;
}
h1 {
font-family: verdana, arial, sans-serif;
color: yellow;
}
button {
padding: 15px;
border-radius: 15px;
}
#gameButtonArea > button {
width: 200px;
height: 200px;
margin: 2px;
}
.hidden {
display: none;
}
#button1 {
background: lightgreen;
}
#button1:active,
#button1.lit {
background: green;
}
#button2 {
background: lightblue;
}
#button2:active,
#button2.lit {
background: blue;
}
#button3 {
background: pink;
}
#button3:active,
#button3.lit {
background: red;
}
#button4 {
background: lightyellow;
}
#button4:active,
#button4.lit {
background: yellow;
}
#button5 {
background: lightgray;
}
#button5:active,
#button5.lit {
background: black;
}
#button6 {
background: white;
}
#button6:active,
#button6.lit {
background: purple;
}
Add a variable let lostCount = 0;.
Change guess else block to:
else {
if (lostCount < 2) lostCount++;
else loseGame();
}
const cluePauseTime = 333; //how long to pause in between clues
const nextClueWaitTime = 1000; //how long to wait before starting playback of the clue sequence
//Global variables
var clueHoldTime = 200; //how long to hold each clue's light/sound
// var pattern = [2, 3, 1, 4, 6, 1, 2, 4, 3, 5];
var pattern = [];
var clueLength = 10;
///////////////////////////////
var progress = 0;
var gamePlaying = false;
var tonePlaying = false;
var volume = 0.5;
var guessCounter = 0;
let lostCount = 0;
function startGame() {
progress = 0;
pattern = []; // reset so array doesn't get longer then 10 if we restart game
for (var i = 0; i < clueLength; i++) {
pattern.push(getRandomInt(5));
}
console.log("pattern: " + pattern);
gamePlaying = true;
document.getElementById("startBtn").classList.add("hidden");
document.getElementById("stopBtn").classList.remove("hidden");
playClueSequence();
}
function stopGame() {
gamePlaying = false;
document.getElementById("startBtn").classList.remove("hidden");
document.getElementById("stopBtn").classList.add("hidden");
}
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max) + 1);
}
function lightButton(btn) {
document.getElementById("button" + btn).classList.add("lit");
}
function clearButton(btn) {
document.getElementById("button" + btn).classList.remove("lit");
}
function playSingleClue(btn) {
if (gamePlaying) {
lightButton(btn);
playTone(btn, clueHoldTime);
setTimeout(clearButton, clueHoldTime, btn);
}
}
function playClueSequence() {
guessCounter = 0;
let delay = nextClueWaitTime; //set delay to initial wait time
for (let i = 0; i <= progress; i++) {
// for each clue that is revealed so far
console.log("play single clue: " + pattern[i] + " in " + delay + "ms");
setTimeout(playSingleClue, delay, pattern[i]); // set a timeout to play that clue
delay += clueHoldTime;
delay += cluePauseTime;
}
}
function loseGame() {
stopGame();
alert("Game Over. You lost.");
}
function winGame() {
stopGame();
alert("Yayyyyy, you win!!");
}
function guess(btn) {
console.log("user guessed: " + btn);
if (!gamePlaying) {
return;
}
if (pattern[guessCounter] == btn) {
if (guessCounter == progress) {
if (progress == pattern.length - 1) {
winGame();
} else {
progress++;
playClueSequence();
}
} else {
guessCounter++;
}
//guessCounter++;
} else {
if (lostCount < 2) lostCount++;
else loseGame();
}
}
// Sound Synthesis Functions
const freqMap = {
1: 261.6,
2: 329.6,
3: 392,
4: 466.2,
5: 432.8,
6: 336.2,
};
function playTone(btn, len) {
o.frequency.value = freqMap[btn];
g.gain.setTargetAtTime(volume, context.currentTime + 0.05, 0.025);
tonePlaying = true;
setTimeout(function () {
stopTone();
}, len);
}
function startTone(btn) {
if (!tonePlaying) {
o.frequency.value = freqMap[btn];
g.gain.setTargetAtTime(volume, context.currentTime + 0.05, 0.025);
tonePlaying = true;
}
}
function stopTone() {
g.gain.setTargetAtTime(0, context.currentTime + 0.05, 0.025);
tonePlaying = false;
}
//Page Initialization
// Init Sound Synthesizer
var context = new AudioContext();
var o = context.createOscillator();
var g = context.createGain();
g.connect(context.destination);
g.gain.setValueAtTime(0, context.currentTime);
o.connect(g);
o.start(0);

How would you increase a variables value every second using a function?

I am trying to make a variable increase every second. What should I include inside the function autoClicker, so that the variable clicks increase by 1 every second? Also, if there are any more problems in the code, could you point them out to me? Sorry if this question seems basic, I am still quite new to JavaScript.
// The variable we are trying to increase
var clicks = 0;
var upgrade1 = 1;
function getClicks() {
clicks += upgrade1;
document.getElementById("clicks").innerHTML = clicks;
};
function buyAutoClicker() {
if (clicks >= 50) {
clicks -= 50
autoClicker()
} else {
alert = "Sorry, you don't have enough clicks to buy this";
}
}
// The function I will use to increase clicks
function autoClicker() {}
You could create an AutoClicker class that has a start, pause, ad update function. It will be in charge of managing the setInterval id.
Edit: I updated it to include upgrade buttons and the target can now be manually clicked.
const upgrades = [{
cost: 50,
rate: 2
}, {
cost: 100,
rate: 4
}];
const main = () => {
const target = document.querySelector('.auto-clicker');
const span = document.querySelector('.info > span');
const btn = document.querySelector('.btn-toggle');
const clicker = new AutoClicker(target, 1000, (clicks) => {
span.textContent = clicks;
}).start();
initializeUpgrades(clicker, upgrades);
btn.addEventListener('click', (e) => {
e.target.textContent = clicker.isRunning() ? 'Start' : 'Pause';
clicker.toggle();
});
};
const initializeUpgrades = (clicker, upgrades) => {
const upgradeContainer = document.querySelector('.upgrades');
upgrades.forEach(upgrade => {
const btn = document.createElement('button');
btn.textContent = upgrade.cost;
btn.value = upgrade.rate;
btn.addEventListener('click', (e) => {
let cost = parseInt(e.target.textContent, 10);
let value = parseInt(e.target.value, 10);
if (clicker.clicks >= cost) {
clicker.clicks -= cost;
clicker.step = value
} else {
console.log(`Cannot afford the ${value} click upgrade, it costs ${cost} clicks`);
}
});
upgradeContainer.appendChild(btn);
});
};
class AutoClicker {
constructor(target, rate, callback) {
if (typeof target === 'string') {
target = document.querySelector(target);
}
this.target = target;
this.rate = rate;
this.callback = callback;
this.init();
}
init() {
this.step = 1;
this.clicks = 0;
this._loopId = null;
this.target.addEventListener('click', (e) => {
this.update();
});
}
isRunning() {
return this._loopId != null;
}
toggle() {
this.isRunning() ? this.pause() : this.start();
}
update() {
this.clicks += this.step;
if (this.callback) {
this.callback(this.clicks);
}
}
start() {
this.update(); // Update immediately
this._loopId = setInterval(() => this.update(), this.rate);
return this;
}
pause() {
clearInterval(this._loopId);
this._loopId = null;
return this;
}
}
main();
.wrapper {
width: 10em;
text-align: center;
border: thin solid grey;
padding: 0.5em;
}
.auto-clicker {
width: 4em;
height: 4em;
background: #F00;
border: none;
border-radius: 2em;
}
.auto-clicker:focus {
outline: none;
}
.auto-clicker:hover {
background: #F44;
cursor: pointer;
}
.info {
margin: 1em 0;
}
.upgrades {
display: inline-block;
}
.upgrades button {
margin-right: 0.25em;
}
<div class="wrapper">
<button class="auto-clicker"></button>
<div class="info">Clicks: <span class="clicks"></span></div>
<button class="btn-toggle">Pause</button>
<div class="upgrades"></div>
</div>
// The variable we are trying to increase
var clicks = 0;
var upgrade1 = 1;
function getClicks() {
clicks += upgrade1;
document.getElementById("clicks").innerHTML = clicks;
};
function buyAutoClicker() {
if (clicks >= 50) {
clicks -= 50
autoClicker()
} else {
alert = "Sorry, you don't have enough clicks to buy this";
}
}
// The function I will use to increase clicks
setInterval(function(){ clicks++;console.log(clicks); }, 1000);
Use setInterval to run a function at a specified interval. This will run increaseClicks every 1000 milliseconds (every second):
function increaseClicks() {
clicks++;
}
var interval = setInterval(increaseClicks, 1000);
Use clearInterval to stop running it:
clearInterval(interval);
You can omit var interval = if you don't want to use clearInterval:
setInterval(increaseClicks, 1000);
There might be several things to improve this code
the use of textContent is preferable to innerHTML, it checks if there are no html tags in the text
then using inline functions like ()=>{} are more useful but in this program it does'nt make a difference, where you to use it in object oriented context you could use it several ways
you don't need document.getElementById, you could just use id.
And finaly (this is just à random tip which has nothing to do with much of anything) you may consider branchless programming because ifs are expensive.
Stackoverflow Branchless Programming Benefits
But anyways you should have fun :)
var clicks = 0;
var upgrade1 = 1;
function getClicks() {
clk.textContent = (clicks += upgrade1);
};
function buyAutoClicker() {
if (clicks >= 50) {
clicks -= 50
setInterval(()=>{getClicks();},1000);
} else {
alert("Sorry, you don't have enough clicks to buy this");
}
}
clk.onclick=()=>{getClicks();};
b.onclick=()=>{buyAutoClicker();};
html,body{height:100%;width:100%;margin:0;}
p{height:50px;width:50px;background:red;}
<p id="clk"></p>
<p id="b"></p>

Count-up Timer required

I've been wanting to create a timer for my website that countsup, and displays alerts at certain intervals. So like, it starts from 0 and counts upwards when the user pushes a button. From there, it will display a a custom alert at certain intervals... (4 minutes for example)... 45 seconds before that interval, I need the number to change to yellow and 10 seconds before that interval, I need it to change to red... then back to the normal color when it passes that interval.
I've got a basic timer code but I am not sure how to do the rest. I am quite new to this. Any help? Thanks so much in advance.
var pad = function(n) { return (''+n).length<4?pad('0'+n):n; };
jQuery.fn.timer = function() {
var t = this, i = 0;
setInterval(function() {
t.text(pad(i++));
}, 1000);
};
$('#timer').timer();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='timer'></div>
You could do something like this
var pad = function (n) {
return ('' + n).length < 4 ? pad('0' + n) : n;
};
jQuery.fn.timer = function () {
var t = this,
i = 0;
setInterval(function () {
t.text(pad(i++));
checkTime(i, t);
}, 1000);
};
$('#timer').timer();
checkTime = function (time, t) {
switch (time -1) {
case 10:
t.css('color','red');
break;
case 20:
t.css('color','yellow');
break;
case 30:
t.css('color','green');
break;
case 40:
t.css('color','black');
break;
default:
}
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='timer'></div>
Something like this should work:
Here is a jsFiddle DEMO
jQuery
$.fn.timer = function (complete, warning, danger) {
var $this = $(this);
var total = 0;
$this.text(total);
var intervalComplete = parseInt(complete, 10);
var intervalWarning = parseInt(intervalComplete - warning, 10);
var intervalDanger = parseInt(intervalComplete - danger, 10);
var clock = setInterval(function () {
total += 1;
$this.text(total);
if (intervalWarning === total) {
// set to YELLOW:
$this.addClass('yellow');
}
if (intervalDanger === total) {
// set to RED:
$this.removeClass('yellow').addClass('red');
}
if (intervalComplete === total) {
// reset:
clearInterval(clock);
$this.removeClass();
alert('COMPLETE!');
}
}, 1000);
};
$(function () {
$('#timer').timer(240, 45, 10);
});
CSS
.red {
background-color: red;
}
.yellow {
background-color: yellow;
}
An additional point:
You should place some error validation within the function to ensure your counter completion time is greater than both the warning and danger time intervals.
You can try something like this:
JSFiddle
This is a pure JS timer code. Also for popup you can use something like Bootbox.js.
Code
function timer() {
var time = {
sec: 00,
min: 00,
hr: 00
};
var finalLimit = null,
warnLimit = null,
errorLimit = null;
var max = 59;
var interval = null;
function init(_hr, _min, _sec) {
time["hr"] = _hr ? _hr : 0;
time["min"] = _min ? _min : 0;
time["sec"] = _sec ? _sec : 0;
printAll();
}
function setLimit(fLimit, wLimit, eLimit) {
finalLimit = fLimit;
warnLimit = wLimit;
errorLimit = eLimit;
}
function printAll() {
print("sec");
print("min");
print("hr");
}
function update(str) {
time[str] ++;
time[str] = time[str] % 60;
if (time[str] == 0) {
str == "sec" ? update("min") : update("hr");
}
print(str);
}
function print(str) {
var _time = time[str].toString().length == 1 ? "0" + time[str] : time[str];
document.getElementById("lbl" + str).innerHTML = _time;
}
function validateTimer() {
var c = "";
var secs = time.sec + (time.min * 60) + (time.hr * 60 * 60);
console.log(secs, finalLimit)
if (secs >= finalLimit) {
stopTimer();
} else if (secs >= errorLimit) {
c = "error";
} else if (secs >= warnLimit) {
c = "warn";
} else {
c = "";
}
var element = document.getElementsByTagName("span");
console.log(element, c)
document.getElementById("lblsec").className = c;
}
function startTimer() {
init();
if (interval) stopTimer();
interval = setInterval(function() {
update("sec");
validateTimer();
}, 1000);
}
function stopTimer() {
window.clearInterval(interval);
}
function resetInterval() {
stopTimer();
time["sec"] = time["min"] = time["hr"] = 0;
printAll();
startTimer();
}
return {
'start': startTimer,
'stop': stopTimer,
'reset': resetInterval,
'init': init,
'setLimit': setLimit
}
};
var time = new timer();
function initTimer() {
time.init(0, 0, 0);
}
function startTimer() {
time.start();
time.setLimit(10, 5, 8);
}
function endTimer() {
time.stop();
}
function resetTimer() {
time.reset();
}
span {
border: 1px solid gray;
padding: 5px;
border-radius: 4px;
background: #fff;
}
.timer {
padding: 2px;
margin: 10px;
}
.main {
background: #eee;
padding: 5px;
width: 200px;
text-align: center;
}
.btn {
-webkit-border-radius: 6;
-moz-border-radius: 6;
border-radius: 6px;
color: #ffffff;
font-size: 14px;
background: #2980b9;
text-decoration: none;
transition: 0.4s;
}
.btn:hover {
background: #3cb0fd;
text-decoration: none;
transition: 0.4s;
}
.warn {
background: yellow;
}
.error {
background: red;
}
<div class="main">
<div class="timer"> <span id="lblhr">00</span>
: <span id="lblmin">00</span>
: <span id="lblsec">00</span>
</div>
<button class="btn" onclick="startTimer()">Start</button>
<button class="btn" onclick="endTimer()">Stop</button>
<button class="btn" onclick="resetTimer()">Reset</button>
</div>
Hope it helps!

How do you call the start and stop function in a timer

Hi I've found a great timer here on SO for a while ago and I was wondering how to call the start and stop function, so when you call the start function the timer starts and when you call the stop function the timer stops. I have tried a lot of different solutions but I can't figure it out anyway here is the code:
<!DOCTYPE html>
<html>
<head>
<title>JS Bin</title>
<style>
.stopwatch {
display: inline-block;
background-color: white;
border: 1px solid #eee;
padding: 5px;
margin: 5px;
}
.stopwatch span {
font-weight: bold;
display: block;
}
.stopwatch a {
padding-right: 5px;
text-decoration: none;
}
</style>
</head>
<body>
<h2>Basic example; update every 1 ms</h2>
<p>click <code>start</code> to start a stopwatch</p>
<pre>
var elems = document.getElementsByClassName("basic");
for (var i=0, len=elems.length; i<len; i++) {
new Stopwatch(elems[i]);
}
</pre>
<div class="basic stopwatch"></div>
<hr>
<script>
var Stopwatch = function(elem, options) {
var timer = createTimer(),
startButton = createButton("start", start),
stopButton = createButton("stop", stop),
resetButton = createButton("reset", reset),
offset,
clock,
interval;
// default options
options = options || {};
options.delay = options.delay || 1;
// append elements
elem.appendChild(timer);
elem.appendChild(startButton);
elem.appendChild(stopButton);
elem.appendChild(resetButton);
// initialize
reset();
// private functions
function createTimer() {
return document.createElement("span");
}
function createButton(action, handler) {
var a = document.createElement("a");
a.href = "#" + action;
a.innerHTML = action;
a.addEventListener("click", function(event) {
handler();
event.preventDefault();
});
return a;
}
function start() {
if (!interval) {
offset = Date.now();
interval = setInterval(update, options.delay);
}
}
function stop() {
if (interval) {
clearInterval(interval);
interval = null;
}
}
function reset() {
clock = 0;
render(0);
}
function update() {
clock += delta();
render();
}
function render() {
timer.innerHTML = clock/1000;
}
function delta() {
var now = Date.now(),
d = now - offset;
offset = now;
return d;
}
// public API
this.start = start;
this.stop = stop;
this.reset = reset;
};
// basic examples
var elems = document.getElementsByClassName("basic");
for (var i=0, len=elems.length; i<len; i++) {
new Stopwatch(elems[i]);
}
</script>
</body>
</html>
If you look through the code, you can see that each button is created using the below function:
function createButton(action, handler) {
var a = document.createElement("a");
a.href = "#" + action;
a.innerHTML = action;
a.addEventListener("click", function(event) {
handler();
event.preventDefault();
});
return a;
}
All this does is append a series of links to the DOM, each with a click event handler calling the relevant function (passed as the handler variable), stop, start or reset.
To call one of these directly, you can simply call the function- e.g. stop()
var Stopwatch = {
init: function(elem, options) {
var timer = createTimer(),
startButton = createButton("start", start),
stopButton = createButton("stop", stop),
resetButton = createButton("reset", reset),
offset,
clock,
interval;
// default options
options = options || {};
options.delay = options.delay || 1;
// append elements
elem.appendChild(timer);
elem.appendChild(startButton);
elem.appendChild(stopButton);
elem.appendChild(resetButton);
// initialize
reset();
// private functions
function createTimer() {
return document.createElement("span");
}
function createButton(action, handler) {
var a = document.createElement("a");
a.href = "#" + action;
a.innerHTML = action;
a.addEventListener("click", function(event) {
handler();
event.preventDefault();
});
return a;
}
function start() {
if (!interval) {
offset = Date.now();
interval = setInterval(update, options.delay);
}
}
function stop() {
if (interval) {
clearInterval(interval);
interval = null;
}
}
function reset() {
clock = 0;
render(0);
}
function update() {
clock += delta();
render();
}
function render() {
timer.innerHTML = clock / 1000;
}
function delta() {
var now = Date.now(),
d = now - offset;
offset = now;
return d;
}
// public API
this.start = start;
this.stop = stop;
this.reset = reset;
}
};
// basic examples
var elems = document.getElementsByClassName("basic");
for (var i = 0, len = elems.length; i < len; i++) {
Stopwatch.init(elems[i]);
}
.stopwatch {
display: inline-block;
background-color: white;
border: 1px solid #eee;
padding: 5px;
margin: 5px;
}
.stopwatch span {
font-weight: bold;
display: block;
}
.stopwatch a {
padding-right: 5px;
text-decoration: none;
}
<div class="basic stopwatch"></div>
<button onclick="Stopwatch.stop()">STOP!</button>

Categories