I can't repeat a function in javascript - javascript

I'm trying to write a simple tabata timer. Until now it work but the problem comes in when I try to repeat the count more times depending on the value stored in a variable.
So, imagine we start from 10 to 0 and we want to repeat this count twice. would say: when I press the button, before the count starts, the program will check if the variable with the number of times is NaN or if it has a number in it. If is NaN because I didn't want to repeat, it just starts to count down from 10 to 0 and it stops. Ok, this part works. But what if I say I want to repeat the count down twice? I put in the variable called "var times" the number of times I want to repeat, let's say 2, then I would use a for loop like:
for(var i=0; i<times; i++){}
But when I start the countdown, instead of repeating twice it skips many numbers as the times variable value. Why is that?
Thanks in advance
Here is my code.
var times = 2;
var counter = 0;
var operation;
document.getElementById("timer").textContent = 10;
function calculate(){
counter = document.getElementById("timer").textContent
operation = setInterval(function(){
if(counter >= 1 && counter <= 10){
counter -- ;
document.getElementById("timer").textContent = counter;
}
else if(counter == 0){
clearInterval(operation);
document.getElementById("timer").textContent = 10;
}
},1000);
}
document.getElementById("btn").addEventListener("click", function(){
for(var i=0; i<times; i++){
calculate();
}
})
.btn{
position: absolute;
width: 100%;
top: 20%;
margin:auto;
text-align: center;
}
.timer{
position: absolute;
width: 100%;
top:30%;
margin:auto;
text-align: center;
font-size: 10rem;
}
<!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">
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body>
<div class="container">
<div class="btn">
<button id="btn">
<h1>Click me</h1>
</button>
</div>
<div class="timer">
<p id="timer"></p>
</div>
</div>
<script src="main.js"></script>
</body>
</html>

I figured it out, the problem there is that when you do the for loop it is calling twice the setinterval, so for this case What You have to do is to use Recursion, here's a working code for this case->
var times = 2;
var counter = 0;
var operation;
document.getElementById("timer").textContent = 10;
function calculate(){
counter = document.getElementById("timer").textContent
operation = setInterval(function(){
if(counter >= 1 && counter <= 10){
counter -- ;
document.getElementById("timer").textContent = counter;
}
else if(counter == 0){
times--
console.log(times)
if(times > 0){
document.getElementById("timer").textContent = 10;
clearInterval(operation);
calculate()
}else if(times == 0){
clearInterval(operation);
document.getElementById("timer").textContent = 10;
}
}
},1000);
}
.btn{
z-index: 9999;
position: absolute;
width: 100%;
top: 20%;
margin:auto;
text-align: center;
}
.timer{
position: absolute;
width: 100%;
top:30%;
margin:auto;
text-align: center;
font-size: 10rem;
}
<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">
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body>
<div class="container">
<div class="btn">
<button onClick="calculate()" id="btn">
<h1>Click me</h1>
</button>
</div>
<div class="timer">
<p id="timer"></p>
</div>
</div>
</body>
</html>

First of all not sure if your logic works or not. I just looking into the code without testing, it seems calculate() > operation = setInterval(function(){... is calling a call back function, which will execute asynchronized.
if you call calculate() twice, it will just trigger the asynchronized method twice at the same time, not in sequence.
It means your logic inside calculate() executed twice at the same time, not in sequence.
you can pass in the times variable into the function like calculate(times), and perform the loop in it, see below example
function calculate(times){
counter = document.getElementById("timer").textContent
operation = setInterval(function(){
/////////////////////////////
// do the times loop here
/////////////////////////////
for(let i=0; i < times; i++){
if(counter >= 1 && counter <= 10){
counter -- ;
document.getElementById("timer").textContent = counter;
} else if(counter == 0) {
clearInterval(operation);
document.getElementById("timer").textContent = 10;
}
}
},1000);
}
document.getElementById("btn").addEventListener("click", function(){
calculate(times);
})

Related

How could I make a function in JS that works like a Upgrade Button

So I want to make a clicker game and I am now at the part where I want to add a function to the 'upgrade click' button so that when I click it, it takes away 'x' amount of money but it makes my clicks generate 'x' more money
Here is my code:
"use strict";
let varible = 0
const button = document.getElementById('dollarButton');
button.addEventListener('click', myFunc);
function myFunc() {
varible++;
document.getElementById('score').innerHTML = "$" + varible
}
img
{
width:200px;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link rel="stylesheet" href="style.css">
</head>
<body>
<button id="dollarButton" style="
border: none;
top: 45%;
left: 20%;
position: absolute;
cursor: pointer;
"><img src="https://www.pngfind.com/pngs/m/94-940164_button-images-png-button-background-image-green-transparent.png" /></button>
<h1 id="score">Time to Make Money!</h1>
<div id="updaCash" class="button red">
<span id="updaCash_text" class="color-white">Upgrade click</span>
</div>
<script src="script.js"></script>
</body>
</html>
You'd want to add a event listener to updaCash that fires whenever it's clicked. I'd also suggest adding a variable that tracks how much money is added per click. For example:
script.js
"use strict";
function myFunc() {
varible += amountToAdd;
document.getElementById('score').innerHTML = "$" + varible
}
function upgradeClick() {
amountToAdd += 1; // 1 could be any other number you'd like
}
let varible = 0;
const amountToAdd = 1;
const button = document.getElementById('dollarButton');
const upgradeButton = document.getElementById("updaCash");
button.addEventListener('click', myFunc);
upgradeButton.addEventListener("click", upgradeClick);
Hope this helps! And good luck on your clicker game :D
You need to change your js code.
So your final Js code look like:
"use strict";
function myFunc() {
varible += amountToAdd;
document.getElementById('score').innerHTML = "$" + varible
}
function upgradeClick() {
amountToAdd += 1;
}
let varible = 0;
const amountToAdd = 1;
const button = document.getElementById('dollarButton');
const upgradeButton = document.getElementById("updaCash");
button.addEventListener('click', myFunc);
upgradeButton.addEventListener("click", upgradeClick);
Similarly Your HTML code looks like:
<button id="dollarButton">
<img src="https://fastly.picsum.photos/id/2/200/300.jpg?hmac=HiDjvfge5yCzj935PIMj1qOf4KtvrfqWX3j4z1huDaU" /></button>
<h1 id="score">Time to Make Money!</h1>
<div id="updaCash" class="button red">
<span id="updaCash_text" class="color-white">Upgrade click</span>
</div>
</button>
And Your CSS code :
#dollarButton{
border: none;
top: 45%;
left: 45%;
position: absolute;
cursor: pointer;
}
Here you have to use another variable to keep track of the amount. So when you click the button x amount is added and next time you click x more amount is added.
"use strict";
let varible = 0
let amount =1
const button = document.getElementById('dollarButton');
button.addEventListener('click', myFunc);
function myFunc() {
varible+=amount;
amount+=1 // replace 1 with x (value you want)
document.getElementById('score').innerHTML = "$" + varible
}
img
{
width:200px;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link rel="stylesheet" href="style.css">
</head>
<body>
<button id="dollarButton" style="
border: none;
top: 45%;
left: 20%;
position: absolute;
cursor: pointer;
"><img src="https://www.pngfind.com/pngs/m/94-940164_button-images-png-button-background-image-green-transparent.png"/></button>
<h1 id="score">Time to Make Money!</h1>
<div id="updaCash" class="button red">
<span id="updaCash_text" class="color-white">Upgrade click</span>
</div>
<script src="script.js"></script>
</body>
</html>

How can i add and display the total number of people counted in this app

I am trying to add and displlay the total number of people that entered the subway in this counting app. I intend to display the total in the Total paragraph. have tried to add the variable 'count' and 'previous' but it outputs the counted number individually insteadof adding them.
let countEl = document.getElementById('count-el');
let count = 0;
function increment() {
count += 1;
countEl.textContent = count;
}
function save() {
let Save = document.getElementById('save-el');
let previous = count + ' - ';
Save.textContent += ' ' + previous;
countEl.textContent = 0;
count = 0;
}
html,
body {
height: 100%;
width: 100%;
background-color: rbg(113, 255, 005);
}
body {
background-color: #398000;
text-align: center;
}
h1,
h2 {
text-align: center;
}
button {
border: none;
padding-top: 10px;
padding-bottom: 10px;
color: #e70d0d;
font-weight: bold;
width: 200px;
margin-bottom: 5px;
border-radius: 5px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Javascript tut</title>
<link href="index.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h1>People entered</h1>
<h2 id="count-el">0</h2>
<button id="increment-Btn" onclick="increment()">INCREMENT</button><br />
<button id="save-btn" onclick="save()">SAVE</button>
<p id="save-el">Previous entries:</p>
<p id="total">Total</p>
<script src="https://replit.com/public/js/replit-badge.js" theme="blue" defer></script>
<script src="index.js"></script>
</body>
</html>
Maybe something like this
const countEl= document.getElementById("count-el");
const totalEl= document.getElementById("total");
const saveEl = document.getElementById("save-el");
let count = 0;
let previous = 0;
let total = 0;
function increment() {
count += 1;
countEl.textContent= count;
}
function save() {
saveEl.textContent += count + ' - ';
total += count;
totalEl.textContent = total;
countEl.textContent= 0;
count = 0;
}
<h2 id = "count-el">0</h2>
<button id="increment-Btn" onclick="increment()">INCREMENT</button><br>
<button id="save-btn" onclick="save()">SAVE</button>
<p id="save-el">Previous entries: </p>
<p>Total: <span id="total"></span></p>
Make a new variable total which after each SAVE is increased by count
Something like this :
function save() {
....
....
total += count;
}
Then display it right next to the "Total:" on your HTML using its id.

Set an element attribute multiple times within a javascript function

im using Vanilla Javascript, and my problem is that i need to render a progress bar in a certain time, but JS only render the final step...
'use strict'
var button = document.getElementById('button');
function sleep(milliseconds) {
const date = Date.now();
let currentDate = null;
do {
currentDate = Date.now();
} while (currentDate - date < milliseconds);
}
function initProgressBar()
{
let progressBar = document.querySelector('#progress-bar'),
count = 25,
total = 64;
progressBar.style = `width:${count}%;`;
while (total > 0) {
sleep(300);
total = Math.trunc(total/2);
count = count + total;
progressBar.style = `width:${count}%;`;
}
}
button.onclick = initProgressBar;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#progress-container {
height: 4px;
width: 100%;
}
#progress-bar {
width: 0%;
height: 100%;
background-color: blueviolet;
}
</style>
</head>
<body>
<div id="progress-container">
<div id="progress-bar"></div>
</div>
<button id=button>press</button>
<script src='prueba.js'></script>
</body>
</html>
The idea is that when the user clicks the button, the progress bar automatically jumps to 25% and then progressively goes to ~ 88% (after that I'll send it to 100% using another function)
The problem is that Javascript only update the element on his last value (88%).
So, is there any way to set the attribute of an element multiple times inside a javasciript function?
The source of the problem is likely the total = Math.trunc(total/2); construction. You're dividing by 2 and then rounding down.
So it's goal is preset to 25 + 64 = 89, meaning 89% is the end.
Once it gets to 88%, it takes that remaining 1, divides it by 2 (1 / 2 = 0.5) and then it rounds that down, so it becomes 0, 88 + 0 = 88, which still isn't 89, so it'll just end up in an infinite loop there.
The way sleep will block the execution thread and might lead to unexpected behaviour in some cases. A better implementation of sleep could be done using Promise and setTimeout.
Here's the snippet using the modified sleep, that works as expected :
'use strict'
var button = document.getElementById('button');
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function initProgressBar()
{
let progressBar = document.querySelector('#progress-bar'),
count = 25,
total = 64;
progressBar.style = `width:${count}%;`;
while (total > 0) {
await sleep(300);
total = Math.trunc(total/2);
count = count + total;
progressBar.style = `width:${count}%;`;
}
}
button.onclick = initProgressBar;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#progress-container {
height: 4px;
width: 100%;
}
#progress-bar {
width: 0%;
height: 100%;
background-color: blueviolet;
}
</style>
</head>
<body>
<div id="progress-container">
<div id="progress-bar"></div>
</div>
<button id=button>press</button>
<script src='prueba.js'></script>
</body>
</html>

i want to display a counter on the screen using innerHTML but it isnt working in a loop even when i use a sleep function?

actually i want a timer so that can countdown from my desired range to 0 .but using innerHTML just displays the 0:00 immediately without showing changes.i used sleep fuction so now the screen just stays the same and then displays zero and not like a countdown what to do?help!!!
function sleep(t){
let timeenter code hereStart=new Date().getTime();
while(true)
{
let elapsedTime=new Date().getTime()-timeStart;
if(elapsedTime>t){
break;
}
}
}
function startLoop(){
let v1=document.getElementById("minutes-input").value;
let v2=document.getElementById("seconds-input").value;
let x1=document.getElementById("minutes");
let x2=document.getElementById("seconds");
for(var i=0;i<v1;i++)
{
x1.innerHTML=i;
console.log(i);
for (var j =1; j<=59; j++) {
sleep(1000);
x2.innerHTML=j;
console.log(j);
}
}
See if this helps. I know that CSS should be in an external file, but hey....
So, here it is...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text" id="minutes-input" value="1">
<input type="text" id="seconds-input" value="10">
<div style="border: 2px solid black; width: 100px; height: 15px;" id="minutes"></div>
<div style="border: 2px solid black; width: 100px; height: 15px;" id="seconds"></div>
<button type="button" onclick="setInterval(updateTime, 1000);">Start counting</button>
<script>
let v1=document.getElementById("minutes-input").value;
let v2=document.getElementById("seconds-input").value;
let x1=document.getElementById("minutes");
let x2=document.getElementById("seconds");
x1.innerHTML = v1; // starting time in minutes
x2.innerHTML = v2; // starting time in seconds
function updateTime() {
x1.innerHTML = v1;
if(v2 > 0) {
x2.innerHTML = --v2;
if(v1 === 0 && v2 === 0) {
return; // stop counting
}
if(v2 === 0) {
v2 = 60
v1--;
}
}
}
</script>
</body>
</html>
If I need to explain something, just ask...

Toggling the value displayed in a DIV depending on which DIV the click is performed

I have 4 (or more) DIV elements on which I want to set this behavior:
In the beginning, all DIVs display A
I click on a random DIV. It must display B. Other DIVs must keep displaying A
If the consecutive click is performed on the same DIV, this later one must display back A. Others must keep displaying A.
If the consecutive click is performed on a different DIV, this later one must display B. All other DIVs must display A
This is what I am working on. I have had hard time to do anything useful.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style>
.divElt {
margin-left: 20%;
width: 80px;
height: 40px;
background-color: blue;
color: white;
font-weight: bold;
text-align: center;
}
</style>
</head>
<body>
<script>
var data = 'B';
function funct() {
var elts = document.getElementsByClassName('divElt')
for(var i = 0; i < elts.length; i++) {
elts[i].innerHTML = data
}
}
</script>
<div class ='divElt' onclick = "funct()"> A
</div>
<br/>
<div class ='divElt' onclick = "funct()"> A
</div>
<br/>
<div class ='divElt' onclick = "funct()"> A
</div>
<br/>
<div class ='divElt' onclick = "funct()"> A
</div>
</body>
</html>
Please help me to resolve this only in JavaScript (no jQuery or other libraries). Thank you a lot in advance.
var letterA = "A";
var letterB = 'B';
//Init with all "A"
var elts = document.getElementsByClassName('divElt');
for (var i = 0; i < elts.length; i++) {
elts[i].innerHTML = letterA;
}
function funct(item) {
for (var i = 0; i < elts.length; i++) {
if (elts[i] !== item)
elts[i].innerHTML = letterA;
else
elts[i].innerHTML = elts[i].innerHTML === letterA ? letterB : letterA;
}
}
.divElt {
margin-left: 20%;
width: 80px;
height: 40px;
background-color: blue;
color: white;
font-weight: bold;
text-align: center;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
</head>
<body>
<script>
</script>
<div class='divElt' onclick="funct(this)">
</div>
<br/>
<div class='divElt' onclick="funct(this)">
</div>
<br/>
<div class='divElt' onclick="funct(this)">
</div>
<br/>
<div class='divElt' onclick="funct(this)">
</div>
</body>
</html>
To uniquely identify the div which was clicked, pass this to the called function like so onclick=func(this)
Then inside your function receive it as a parameter
function func(elem) {
var elts = document.getElementsByClassName('divElt');
for(var i = 0; i < elts.length; i++) {
elts[i].innerHTML = 'A';
}
elem.innerHTML = elem.innerHTML === 'B' ? 'A' : 'B';
}

Categories