How to add a number to a var every second - javascript

As a beginner in Javascript, I'm trying to make a clicker game. I don't know how to add a number to a var every second
Below is the code at the moment. I'm not sure how to make one of my "dank miners" automatically add coins every second to the player. Let's say there are two auto miners, then the player earns 4 coins per second. Also how to display how much the player is automatically making.
Thanks!
let borkCoins = 0;
let dankMiner = 0;
const earnBork = () => {
borkCoins += 1;
displayScreen();
};
const buydankMiner1 = () => {
if (borkCoins >= 20) {
dankMiner += 1;
borkCoins -= 20;
displayScreen();
} else {
alert("Insufficient funds!")
}
};
const displayScreen = () => {
document.getElementById("bork-coins").innerText =
borkCoins;
document.getElementById("dankMiner").innerText =
dankMiner;
};
displayScreen();
<h3>Your BorkCoins: <span id="bork-coins"></h3>
<img src="https://i.pinimg.com/736x/ef/6a/cf/ef6acfc481b76637b71d4a71db7de82a--dog-birthday-animal-memes.jpg"
height="80" width="80" id="bork-coins" onclick="earnBork();">
<p>Click on Gabe the Doggo to earn a BorkCoin!</p>
<h3>Shop</h3>
<p>Dank Miner <i>(2 BorkCoins/sec)</i>
<br>Your Dank Miner(s): <span id="dankMiner"></span></p>
<button id="dank-miner" onclick="buydankMiner1();">Buy 1 (20 BorkCoins)</button>

You can use setInterval function and do something like this :
let borkCoins = 0;
let dankMiner = 0;
const earnBork = () => {
borkCoins += 1;
displayScreen();
};
/* Code Added */
setInterval(earnBork, 1000);
/*--*/
const buydankMiner1 = () => {
if (borkCoins >= 20) {
dankMiner += 1;
borkCoins -= 20;
displayScreen();
} else {
alert("Insufficient funds!")
}
};
const displayScreen = () => {
document.getElementById("bork-coins").innerText =
borkCoins;
document.getElementById("dankMiner").innerText =
dankMiner;
};
displayScreen();
<h3>Your BorkCoins: <span id="bork-coins"></span></h3>
<img src="https://i.pinimg.com/736x/ef/6a/cf/ef6acfc481b76637b71d4a71db7de82a--dog-birthday-animal-memes.jpg" height="80" width="80" id="bork-coins" onclick="earnBork();">
<p>Click on Gabe the Doggo to earn a BorkCoin!</p>
<h3>Shop</h3>
<p>Dank Miner <i>(2 BorkCoins/sec)</i>
<br>Your Dank Miner(s): <span id="dankMiner"></span></p>
<button id="dank-miner" onclick="buydankMiner1();">Buy 1 (20 BorkCoins)</button>

Add an interval that checks for the number of miners:
setInterval(() => {
if (dankMiner > 0) {
borkCoins += dankMiner;
displayScreen();
}
}, 1000);

Related

how to choose a number to decrement below zero

I'm learning js. I want to make an alarm clock app. Currently I'm working on setting the time. I created buttons that increment and decrement the hour. I want to decrement below zero to 23. I also want to stop the increment at 23 and then continue with 0. Can anyone help me? If someone tells me the first part of the condition, I'll be able to figure out the other part.
let myHour = document.querySelector(".hours");
let myHourConverted = Number(myHour.innerText);
const hourDecrementBtn = document.querySelector(".hour-decrement");
const hourIncrementBtn = document.querySelector(".hour-increment");
hourDecrementBtn.addEventListener("click", decrementHour);
function decrementHour() {
let hourDecrement = --myHourConverted;
myHour.innerText = hourDecrement;
if (hourDecrement < 0) {
hourDecrement = 23;
}
}
hourIncrementBtn.addEventListener("click", incrementHour);
function incrementHour() {
let hourIncrement = ++myHourConverted;
myHour.innerText = hourIncrement;
if (hourIncrement > 23) {
hourIncrement = 0;
}
}
<div class="timer-hours-container">
<span class="hours">00</span>
<div class="hours-buttons-container">
<button class="hour-decrement timer-button">〈</button>
<button class="hour-increment timer-button">〉</button>
The problem is that when you make the change to decrement or increment from 23 to 0, you change the content of hourIncrement but not of myHourConverted, I leave you a small solution.
const myHour = document.querySelector(".hours");
let myHourConverted = Number(myHour.innerText);
const hourDecrementBtn = document.querySelector(".hour-decrement");
const hourIncrementBtn = document.querySelector(".hour-increment");
function decrementHour() {
if (--myHourConverted < 0) myHourConverted = 23;
myHour.innerText = myHourConverted;
}
function incrementHour() {
if (++myHourConverted > 23) myHourConverted = 0;
myHour.innerText = myHourConverted;
}
hourDecrementBtn.addEventListener("click", decrementHour);
hourIncrementBtn.addEventListener("click", incrementHour);
<div class="timer-hours-container">
<span class="hours">00</span>
<div class="hours-buttons-container">
<button class="hour-decrement timer-button">〈</button>
<button class="hour-increment timer-button">〉</button>
</div>
</div>

JS counting numbers with thousands separator

For example, I want to display the number 90,000 while it is counting up.
I have already managed to count up with the following code, but without "." or ",":
<div class="fact">
<div class="number" num="90000">0</div>
</div>
const counters = document.querySelectorAll('.number');
const speed = 500;
counters.forEach( counter => {
const animate = () => {
const value = +counter.getAttribute('num');
const data = +counter.innerText;
const time = value / speed;
if(data < value) {
counter.innerText = Math.ceil(data + time);
setTimeout(animate, 1);
}else{
counter.innerText = value;
}
}
animate();
});
Have already found examples with thousands separator but I can't manage to convert it to my project.
while (/(\d+)(\d{3})/.test(val.toString())){
val = val.toString().replace(/(\d+)(\d{3})/, '$1'+','+'$2');
I have little experience with javascript.
Per my comment, Keep data separate from formatting
const counters = document.querySelectorAll('.number');
const speed = 500;
const formatter = new Intl.NumberFormat();
counters.forEach(counter => {
const animate = () => {
let value = +counter.dataset.num;
let data = +counter.dataset.state;
let time = value / speed;
if (data < value) {
counter.dataset.state = Math.ceil(data + time);
setTimeout(animate, 1);
}
counter.innerText = formatter.format(counter.dataset.state);
}
animate();
});
<div class="fact">
<div class="number" data-num="90000" data-state="0">0</div>
<div class="number" data-num="45000" data-state="0">0</div>
</div>

Large numbers in count-up show NaN in safari browser

I have created a count-up function in Vanilla JS. Everything works well. The counter starts when you scroll down to it. Unfortunately the big number 35 000 000 shows up as NaN in the iOS Safari browser. I have no idea why. Please help. It looks like large numbers don't work in iOS Safari browser.
var animationDuration = 3000;
var frameDuration = 1000 / 60;
var totalFrames = Math.round(animationDuration / frameDuration);
var easeOutQuad = t => t * (2 - t);
var animateCountUp = el => {
let frame = 0;
var countTo = parseInt(el.innerHTML.replace(/ /g, ''), 10);
var counter = setInterval(() => {
frame++;
var progress = easeOutQuad(frame / totalFrames);
var currentCount = Math.round(countTo * progress);
if (parseInt(el.innerHTML, 10) !== currentCount) {
el.textContent = currentCount.toLocaleString().replace(/,/g, ' ');
}
if (frame === totalFrames) {
clearInterval(counter);
}
}, frameDuration);
};
var count = document.querySelectorAll('.countup'),
once = 1;
document.addEventListener('scroll', function() {
if (once == 1 && count[0].getBoundingClientRect().top < window.innerHeight) {
once = 0;
count.forEach(animateCountUp);
}
});
<div style="position: fixed">
<span class="countup">12 500</span>
<span class="countup">35 000 000</span>
</div>
<div style="height: 5000px"></div>
Using innerHTML for this is slightly less than ideal, and in fact iOS Safari is adding markup to your large number which is tripping up your code. It's identifying it as a telephone number and changing the inner HTML of that element to: 35 000 000. That's very surprising, but you can see it here:
console.log(document.querySelector(".countup").innerHTML);
<span class="countup">35 000 000</span>
Note: Only on iOS Safari as far as I can tell.
Using textContent instead works, since the text is unchanged:
var animationDuration = 3000;
var frameDuration = 1000 / 60;
var totalFrames = Math.round(animationDuration / frameDuration);
var easeOutQuad = t => t * (2 - t);
var animateCountUp = el => {
let frame = 0;
var countTo = parseInt(el.textContent.replace(/ /g, ''), 10);
var counter = setInterval(() => {
frame++;
var progress = easeOutQuad(frame / totalFrames);
var currentCount = Math.round(countTo * progress);
if (parseInt(el.textContent, 10) !== currentCount) {
el.textContent = currentCount.toLocaleString().replace(/,/g, ' ');
}
if (frame === totalFrames) {
clearInterval(counter);
}
}, frameDuration);
};
var count = document.querySelectorAll('.countup'),
once = 1;
document.addEventListener('scroll', function() {
if (once == 1 && count[0].getBoundingClientRect().top < window.innerHeight) {
once = 0;
count.forEach(animateCountUp);
}
});
<div style="position: fixed">
<span class="countup">12 500</span>
<span class="countup">35 000 000</span>
</div>
<div style="height: 5000px"></div>
You can also tell iOS Safari not to do this by adding a meta tag as described in this question's answers:
<meta name="format-detection" content="telephone=no">
but as far as I can tell that disables it page-wide.
Why not use counto instead of using DOM as a storage for the number to counto?
And as TJ said, the issue was Safari's handling of your number when using innerHTML instead of textContent
if (currentCount<=countTo) {
el.textContent = currentCount.toLocaleString().replace(/,/g, ' ');
}
Tested on iOS 14.4
https://plungjan.name/SO/tl.html
var animationDuration = 3000;
var frameDuration = 1000 / 60;
var totalFrames = Math.round(animationDuration / frameDuration);
var easeOutQuad = t => t * (2 - t);
var animateCountUp = el => {
let frame = 0;
var countTo = parseInt(el.textContent.replace(/ /g, ''), 10); // do not use innerHTML here
var counter = setInterval(() => {
frame++;
var progress = easeOutQuad(frame / totalFrames);
var currentCount = Math.round(countTo * progress);
if (currentCount<=countTo) {
el.textContent = currentCount.toLocaleString().replace(/,/g, ' ');
}
if (frame === totalFrames) {
clearInterval(counter);
}
}, frameDuration);
};
var count = document.querySelectorAll('.countup'),
once = 1;
document.addEventListener('scroll', function() {
if (once == 1 && count[0].getBoundingClientRect().top < window.innerHeight) {
once = 0;
count.forEach(animateCountUp);
}
});
<div style="position: fixed">
<span class="countup">12 500</span>
<span class="countup">35 000 000</span>
</div>
<div style="height: 5000px"></div>

HTML: How to get multiple timers to combine

I am building a timer based on user inputs. Below is how to code should work:
User inputs:
Time on: 30s
Time off: 10s
Number of sets: 4
Number of exercises per set: 5
Rest in between sets: 30s
With the above user inputs the timer will do this:
Hopefully that makes sense on what It is supposed to do. I am currently trying to implement the rest in between sets. Does anyone know how I could make that happen with how my code currently is? Also totalTime already includes the amount of time the rest in between sets would add on if that helps.
var numsets = document.getElementById("userInput1");
var numex = document.getElementById("userInput2");
var numwork = document.getElementById("userInput3");
var numrest = document.getElementById("userInput4");
var numrestafterset = document.getElementById("userInput5");
var sets;
var OGtimeon;
var OGtimeoff;
var totalTime;
var timeRemaining;
var hasBeenStarted = false; // Boolean value to test what time to use
var isTimeON = true;
var timeon;
var timeoff;
var timeonRemaining;
var timeoffRemaining;
var setsRemaining;
var OGsets;
var Prepare;
var OGExPS;
var OGTOASets;
var ExercisePS;
var RestAfterS;
var Intervals
var j = 0;
var ExercisesRemaining;
var RestRemaining;
// function sleep(milliseconds) { //function I found online to create a sleep function
// const date = Date.now();
// let currentDate = null;
// do {
// currentDate = Date.now();
// } while (currentDate - date < milliseconds);
// }
// function updateRest() {
// if (RestAfterS > 0) {
// interval3 = setInterval(RestCount, 1000);
// }
// else {
// startTime();
// }
// function RestCount() {
// while (RestAfterS != 0) {
// RestAfterS--;
// }
// j = 0;
// }
function updatePrep() {
if (hasBeenStarted == false) {
Prepare = 5;
interval2 = setInterval(PrepCount, 1000);
}
else {
startTime();
}
}
function PrepCount() {
let seconds = parseFloat(Prepare) % 60;
if (Prepare == 0) {
clearInterval(interval2);
startTime();
}
else {
PWR.innerHTML = "Get Ready!";
textarea.innerHTML = Prepare;
console.log(Prepare);
Prepare--;
}
}
function startTime() {
// Set values in code
OGsets = numsets.value;
OGtimeon = numwork.value;
OGtimeoff = numrest.value;
OGTOASets = numrestafterset.value;
OGExPS = numex.value;
timeon = (hasBeenStarted)? timeonRemaining : OGtimeon;
timeoff = (hasBeenStarted)? timeoffRemaining : OGtimeoff;
sets = (hasBeenStarted)? setsRemaining : OGsets;
ExercisePS = (hasBeenStarted)? ExercisesRemaining : OGExPS;
RestAfterS = (hasBeenStarted)? RestRemaining : OGTOASets;
// How much time on timer
// Var = (expression)? true : false this is basically an if statement
totalTime = (hasBeenStarted)? timeRemaining : ((parseFloat(OGtimeon)*parseFloat(sets)*parseFloat(ExercisePS))+(parseFloat(OGTOASets)*(parseFloat(sets)-1))+(parseFloat(OGtimeoff)*(parseFloat(sets)*(parseFloat(ExercisePS)-1))));
Intervals = ((parseFloat(sets)*parseFloat(ExercisePS))+((parseFloat(sets)-1))+((parseFloat(sets)*(parseFloat(ExercisePS)-1))));
hasBeenStarted = true;
// Start timer
interval = setInterval(updateCountdown, 1000);
}
function updateCountdown() {
IntervalsLeft.innerHTML = Intervals;
setsLeft.innerHTML = sets;
var minutes= Math.floor (parseFloat(totalTime) / 60);
var seconds = parseFloat(totalTime) % 60;
if (seconds < 10) {
textareaRemaining.innerHTML = minutes + ":0" + seconds;
} else {
textareaRemaining.innerHTML = minutes + ":" + seconds;
}
// Update TimeON / Time OFF
if(isTimeON){
PWR.innerHTML = "Work!";
textarea.innerHTML = timeon;
timeon--;
if(timeon == 0){
isTimeON = false;
timeon = OGtimeon;
Intervals--;
IntervalsLeft.innerHTML = Intervals;
}
}
//BELOW IS THE AREA I AM STUCK ON
else{
textarea.innerHTML = timeoff;
timeoff--;
PWR.innerHTML = "Rest!";
if(timeoff == 0){
isTimeON = true;
timeoff = OGtimeoff;
j++;
Intervals--;
IntervalsLeft.innerHTML = Intervals;
if (j == OGExPS) {
sets--;
//updateRest();
j = 0;
}
}
}
if( totalTime == 0 ){
clearTimeout(interval);
hasBeenStarted = false;
console.log(sets);
sets--;
setsLeft.innerHTML = sets;
PWR.innerHTML = "OMG YOU'RE DONE";
}
totalTime--;
}
function updateRest() {
if (RestAfterS > 0) {
interval3 = setInterval(RestCount, 5000);
}
else {
startTime();
}
}
function RestCount() {
while (RestAfterS != 0) {
RestAfterS--;
PWR.innerHTML = "Set Rest!";
textarea.innerHTML = RestAfterS;
}
j = 0;
clearInterval(interval3);
}
function stop(){
timeRemaining = totalTime;
timeonRemaining = timeon;
timeoffRemaining = timeoff;
RestRemaining = RestAfterS;
ExercisesRemaining = OGExPS;
setsRemaining = sets;
clearTimeout(interval);
// document.getElementById("Counter").innerHTML = j;
}
p {
display: inline-flex;
align-items: center;
}
label {
float: left;
display: block;
}
#userInput1 {
display: flex;
margin-bottom: 10px;
}
#userInput2 {
display: flex;
margin-bottom: 10px;
}
#userInput3 {
display: flex;
margin-bottom: 10px;
}
#userInput4 {
display: flex;
margin-bottom: 10px;
}
#userInput5 {
display: flex;
margin-bottom: 10px;
}
#Prepare {
display: flex;
margin-bottom: 10px;
}
#sets {
display: flex;
margin-bottom: 10px;
}
#timeon {
display: flex;
margin-bottom: 10px;
}
#timeoff {
display: flex;
margin-bottom: 10px;
}
#TotalTime {
display: flex;
margin-bottom: 10px;
}
#Counter {
display: flex;
margin-bottom: 10px;
}
input {
height: 20px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-compatible" content="ie=edge" />
<title>Document</title>
<link rel="stylesheet" href="Countdown From Scratch.css" />
</head>
<script src="Countdown From Scratch.js" defer></script>
<body>
<label>Number of Sets </label>
<input id="userInput1" type="numsets" value = "0"/>
<label>Number of Exercises per Set </label>
<input id="userInput2" type="numex" value = "0"/>
<label>Time to Work </label>
<input id="userInput3" type="numwork" value = "0"/>
<label>Time to Rest </label>
<input id="userInput4" type="numrest" value = "0"/>
<label>Time Inbetween Sets </label>
<input id="userInput5" type="numrestafterset" value = "0"/>
<p id="Prepare"></p>
<div id="sets"> </div>
<div id="timeon"> </div>
<div id="timeoff"> </div>
<div id="TotalTime"> </div>
<textarea id="textarea" placeholder="00:00"></textarea>
<textarea id="PWR" placeholder="Hello!"></textarea>
<textarea id="textareaRemaining" placeholder="00:00"></textarea>
<textarea id="setsLeft" placeholder="00"></textarea>
<textarea id="IntervalsLeft" placeholder="00"></textarea>
<button onclick="updatePrep()">Start time</button>
<button onclick="stop()">Stop time</button>
</body>
</html>
I think I have a rough idea of what you are trying to accomplish here, but please let me know if I have misinterpreted anything.
Suppose you want to execute a sequence of effects with some duration in between them. To keep the example small, we'll use console.log as a stand-in for any effect you'd want to execute (for instance, setting the innerHTML of a DOM element).
As a first example, here we wait for 1 second, display "Hello", then wait for 1.5 seconds and display "There":
setTimeout(() => {
console.log('Hello');
setTimeout(() => {
console.log('There');
}, 1500);
}, 1000);
We can clarify this by describing the common parts as a function:
function logAfter(message, delay, callback) {
setTimeout(() => {
console.log(message);
if (callback) callback();
}, delay);
}
Then our example can be written as:
logAfter('Hello', 1000, () => {
logAfter('There', 1500);
});
As another example that is perhaps more relevant to your project, here is how we can create a "loop" that performs an effect multiple times:
function logNAfter(message, times, delay, callback) {
if (times === 0 && callback) {
callback();
}
else {
setTimeout(() => {
console.log(message);
logNAfter(message, times-1, delay, callback);
}, delay);
}
}
We could use this to display "Hi There!" 3 times, each separated by half a second, and then display "Goodbye!" once, 2 seconds later:
logNAfter('Hi There!', 3, 500, () => {
logAfter('Goodbye!', 2000);
});
In theory, you could create an arbitrarily-long sequence of appropriately spaced effects in this way. However, I should also mention that many would prefer to describe these effects as Promises instead:
function logAfter(message, delay) {
return new Promise(resolve => {
setTimeout(() => {
console.log(message);
resolve();
}, delay);
});
}
function logNAfter(message, times, delay) {
if (times === 0) {
return Promise.resolve();
} else {
return logAfter(message, delay)
.then(() => logNAfter(message, times-1, delay));
}
}
The original examples then become:
logAfter('Hello', 1000)
.then(() => logAfter('There', 1500));
logNAfter('Hi There!', 3, 500)
.then(() => logAfter('Goodbye!', 2000));
This is arguably only a slight improvement over the callback-style approach above, but it is much clearer if you are able to use async/await:
async function logAfter(message, delay) {
return new Promise(resolve => {
setTimeout(() => {
console.log(message);
resolve();
}, delay);
});
}
async function logNAfter(message, times, delay) {
for (let i = 0; i < times; ++i) {
await logAfter(message, delay);
}
}
async function demoSequence1() {
await logAfter('Hello', 1000);
await logAfter('There', 1500);
}
async function demoSequence2() {
await logNAfter('Hi There!', 3, 500);
await logAfter('Goodbye!', 2000);
}
Hope that helps!
I like Williams suggested of breaking it down into different timers that could be controlled easier by the user. However, using this approach, I personally ran into the issue of how to pause the timer.
I decided to take a slightly different approach. From the table given, there is a fairly clear pattern of how the timer needs to be set up.The timer generally alternates between "Workout time" and "Rest time" for the whole duration. Rest time can take 3 different values:
Rest time between exercises
Rest time between Sets
The workout is complete
Since all of these values are known when the the values are inputed, my approach is set up the course of the timer before starting the timer. This creates a little bit of setup time but I believe this is negotiable and will not impact performance heavily. To do this, I created a created an array before starting the timer. Each item in this array contains data including the total time remaining, the current set, the label (Working out or resting), and the label timer. After creating this array, we can just create a timer that is based off the number of items in the array. I hope that this little explanation helps you understand my solution a little bit better.
Index.html
<!DOCTYPE html>
<html>
<style>
td, th {
text-align: left;
padding: 8px;
}
</style>
<head>
<title>Timer</title>
</head>
<body>
<!-- Inputs -->
<h2>Inputs</h2>
<p>
<label for="sets-input">Number of Sets: </label>
<input type="number" id="sets-input" min="1" max="3600">
</p>
<p>
<label for="exercises-input">Number of Exersizes per Set: </label>
<input type="number" id="exercises-input" min="1" max="3600">
</p>
<p>
<label for="workout-input">Exersise Time: </label>
<input type="number" id="workout-input" min="1" max="3600">
</p>
<p>
<label for="exersiseRest-input">Rest between exersises: </label>
<input type="number" id="exersiseRest-input" min="1" max="3600">
</p>
<p>
<label for="setRest-input">Rest between Sets: </label>
<input type="number" id="setRest-input" min="1" max="3600">
</p>
<!-- Buttons -->
<p>
<button id="start-button">Start</button>
<button id="reset-button">Reset</button>
</p>
<!-- Timer Display -->
<h2>Outputs:</h2>
<table>
<tr>
<th>Total Time Remaining: </th>
<td id="timer-display">???</td>
</tr>
<tr>
<th>Set Number: </th>
<td id="set-display">???</td>
</tr>
<tr>
<th id="label-display">???</th>
<td id="labelTimer-display">???</td>
</tr>
</table>
<script src="tabada.js"></script>
</body>
</html>
Tabada.js
//-----------------------------------------------------------------------------------------------
// GLOBAL VARIABLES
//-----------------------------------------------------------------------------------------------
// HTML
var setsInput = document.getElementById("sets-input");
var exersisesInput = document.getElementById("exercises-input");
var workoutInput = document.getElementById("workout-input");
var exersiseRestInput = document.getElementById("exersiseRest-input");
var setRestInput = document.getElementById("setRest-input");
var timerDisplay = document.getElementById("timer-display");
var setDisplay = document.getElementById("set-display");
var labelDisplay = document.getElementById("label-display");
var labelTimerDisplay = document.getElementById("labelTimer-display");
var startButton = document.getElementById("start-button");
var resetButton = document.getElementById("reset-button");
// JavaScript
var sets = 2;
var exersises = 3;
var workout = 5;
var exersiseRest = 2;
var setRest = 3;
var totalTime = -1;
var myInterval = -1;
var tabadaArray = [];
var tabadaIndex = 0;
//-----------------------------------------------------------------------------------------------
// BUTTON FUNCTIONS
//-----------------------------------------------------------------------------------------------
// Start / Pause Button
startButton.addEventListener("click", function(event){
// Set up Tabada Timer
if (totalTime == -1){
collectInputs(); // Comment this line for testing without inputs
calculateTotalTime();
createTabadaArray();
}
// Start timer
if (myInterval == -1){
startButton.innerHTML = "Pause";
myInterval = setInterval(tabadaTimer, 1000);
}
// Pause timer
else{
startButton.innerHTML = "Start";
clearInterval(myInterval);
myInterval = -1
}
});
// Reset Button
resetButton.addEventListener("click", function(event){
// Stop Timer
clearInterval(myInterval);
// Refresh Timer Display
calculateTotalTime();
updateOutputs(totalTime, 1, 'Workout', workout);
totalTime=-1; // Alows user to change input values before clicking start button.
// Reset start / pause button
myInterval = -1;
startButton.innerHTML = "Start";
});
//-----------------------------------------------------------------------------------------------
// SETUP FOR TABADA TIMER
//-----------------------------------------------------------------------------------------------
function collectInputs(){
sets = parseFloat(setsInput.value);
exersises = parseFloat(exersisesInput.value);
workout = parseFloat(workoutInput.value);
exersiseRest = parseFloat(exersiseRestInput.value);
setRest = parseFloat(setRestInput.value);
}
function calculateTotalTime(){
let totalWorkoutTime = workout * exersises * sets;
let totalExersiseRest = exersiseRest * (exersises - 1) * sets;
let totalSetsRest = setRest * (sets - 1);
totalTime = totalWorkoutTime + totalExersiseRest + totalSetsRest;
}
function createTabadaArray() {
tabadaIndex = 0; // Global variable used for tabada timer
tabadaArray = [];
for( let set=1; set<=sets; set++ ){
for( let exersise=1; exersise<=exersises; exersise++){
// Workout
addTimeBlock(set, 'Workout', workout);
// Exersise Rest
if ( exersise < exersises){
addTimeBlock(set, 'Rest', exersiseRest);
}
// Set Rest
else if( set < sets){
addTimeBlock(set, 'Rest', setRest);
}
// Done
else{break;} // Very end exersize has no rest, so we must break the loop.
}
}
}
function addTimeBlock(set, label, labelTime) {
// Add a sub timer to the array (workout, exersice rest, or set rest)
for (let i=labelTime; i>0; i--) {
tabadaArray.push({
"totalTimeRemaining" : totalTime--,
"set" : set,
"label" : label,
"labelTimeRemaining" : i,
});
}
}
//-----------------------------------------------------------------------------------------------
// TABADA TIMER
//-----------------------------------------------------------------------------------------------
function tabadaTimer(){
// Still time left
if (tabadaIndex < tabadaArray.length){
let displayInfo = tabadaArray[tabadaIndex];
updateOutputs( displayInfo.totalTimeRemaining,
displayInfo.set,
displayInfo.label,
displayInfo.labelTimeRemaining );
tabadaIndex++;
}
// End of tabada timer
else{
clearInterval(myInterval); // stop timer
updateOutputs(0, 1, 'Rest', 0);
totalTime = -1
}
}
function updateOutputs(totalTimeRemaining, setNumber, label, labelTimeRemaining){
timerDisplay.innerHTML = convertSeconds(totalTimeRemaining);
setDisplay.innerHTML = setNumber;
labelDisplay.innerHTML = label;
labelTimerDisplay.innerHTML = convertSeconds(labelTimeRemaining);
}
function convertSeconds(s){
// Seconds -> mm:ss format
// Calculate
let minutes = Math.floor(s/60);
let seconds = s%60;
// Format
let formattedminutes = ("0" + minutes).slice(-2);
let formattedseconds = ("0" + seconds).slice(-2);
return formattedminutes + ':' + formattedseconds;
}

How to fix clearInterval() not stopping the interval?

I made an interval connected to a button that only runs when you have a certain amount of money and lemonade. Then I created an if statement that makes it so that when you run out of lemonade, then the interval stops. I used clearInterval() and for some reason the interval doesn't stop, and the number of lemonade goes into the negatives. Obviously you can't have a negative amount of something!
I've looked at all of the other questions with similar problems to me, but they didn't really answer my question. They all have different variables and it was hard to find an answer pertaining to my code.
Here's my code:
let autoBtnTwo = document.getElementById("autoBtnTwo");
let lemonade = 0;
let btnTwo = document.getElementById("btnTwo")
function btnTwoCost() {
wallet.removeCash(20);
update();
document.getElementById("lemonade").innerHTML = lemonade += 30
}
function double() {
if (wallet.getCash() >= 50) {
wallet.addCash(2)
update();
document.getElementById("lemonade").innerHTML = lemonade -= 1;
}
}
function autoLemonade() {
if (wallet.getCash() >= 3000) {
wallet.removeCash(3000);
var myint = setInterval(double, 1000);
autoBtnTwo.disabled = false;
update();
}
if (wallet.getCash() <= 2999) {
autoBtnTwo.disabled = true;
}
if (lemonade <= 0) {
autoBtnTwo.disabled = true;
btnTwo.disabled = true;
}
}
function stopInterval() {
var myint = setInterval(double, 1000);
if (lemonade <= 0) {
clearInterval(myint);
stopInterval();
}
}
function thousand() {
wallet.addCash(1000)
update();
if (wallet.getCash() >= 3000) {
autoBtnTwo.disabled = false;
}
}
function Wallet() {
return {
addCash: function(val) {
number += val;
},
getCash: function() {
return number;
},
removeCash: function(val) {
number -= val;
}
}
}
var number = 0;
const wallet = new Wallet();
var SUFFIXES = 'KMBTqQsSOND';
function update() {
document.getElementById('number').textContent = getSuffixedNumber(wallet.getCash());
}
function getSuffixedNumber(num) {
var power = Math.floor(Math.log10(num));
var index = Math.floor(power / 3)
num = num / Math.pow(10, (index * 3)); // first 3 digits of the number
return num.toFixed(1) + (SUFFIXES[index - 1] || ''); // default to no suffix if it gets an out of bounds index
}
<button onclick="autoLemonade()" class="chocolate-bar-auto" id="autoBtnTwo" disabled>
Hire worker: <br> -$3000<br> Sells Lemonade
</button>
<button onclick="thousand()">to get to $3000 for testing </button>
<button onclick="btnTwoCost()"> buy lemonade -$20</button>
<button onclick="double()">sell lemonade </button>
<div class="cash-div">
Cash: <div id="number">0</div>
</div>
<div class="lemonade-div">
Lemonade: <div id="lemonade">0</div>
</div>
Sorry if this version is glitchy. All of the code I used to prevent the glitches makes the code longer, which it is already long enough. press the $3,000 button 4 times, then the buy lemonade, and then the hire worker button and you will see what happens once it gets to 0.
The interval should stop adding money, and stop reducing the amount of lemonade when lemonade reaches 0, but instead it keeps going into the negatives.

Categories