Reputation: 65
I'm kind of a noob to JS and I'm starting to get used to the basics but I am struggling on passing a variable from within a function that is already in a function.. to another function.
I have looked up scope and I have declared a global variable but when I console log it displays undefined. Here is my code. The project is a bar that shows how long you are into your shift at work in percentage.
I need the percentage variable to be passed out of the timed loop and into the moveLoadingBar Function so that the bar will slowly move up as the day goes on. What am I missing?
const target = 100; //percent
let percentage;
function setup() {
//Set the start point for today at 09:00:00am
let start = new Date();
start.setHours(9, 00, 00);
setInterval(timeConversion, 1000);
function timeConversion() {
//Work out the difference in miliseconds from now to the start point.
let now = new Date();
let distance = now -= start;
// Time calculations for hours, minutes and seconds
let hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
let seconds = Math.floor((distance % (1000 * 60)) / 1000);
let miliseconds = distance;
//Percentage of day complete **** struggling to pass variable to global variable ****
percentage = (miliseconds / target) * 100
}
}
function moveLoadingBar() {
let loadingBar = document.getElementById("myBar");
let id = setInterval(frame, 1000);
function frame() {
if (percentage >= target) {
clearInterval(id);
} else {
loadingBar.style.width = percentage + "%";
}
}
}
//debugging
setup();
moveLoadingbar();
console.log(percentage);
console.log(target);
CSS
#myProgress {
width: 100%;
background-color: #ddd;
}
#myBar {
width: 1%;
height: 30px;
background: linear-gradient(90deg, #00C9FF 0%, #92FE9D 100%);
}
HTML
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="stylesheet.css">
<title>Hello world</title>
</head>
<body>
<h1>Progress Bar</h1>
<div id="myProgress">
<div id="myBar"></div>
</div>
<br>
</body>
<script src="index.js"></script>
</html>
Upvotes: 1
Views: 162
Reputation: 1928
moveLoadingbar is nested function inside Setup function. Which you cant access directly,and so it was throwing an error.
const target = 100; //percent
var percentage;
function setup() {
debugger;
//Set the start point for today at 09:00:00am
let start = new Date();
start.setHours(9, 00, 00);
setInterval(timeConversion, 1000);
function timeConversion() {
//Work out the difference in miliseconds from now to the start point.
let now = new Date();
let distance = now -= start;
// Time calculations for hours, minutes and seconds
let hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
let seconds = Math.floor((distance % (1000 * 60)) / 1000);
let miliseconds = distance;
//Percentage of day complete **** struggling to pass variable to global variable ****
percentage = (miliseconds / target) * 100;
}
}
function moveLoadingBar() {
let loadingBar = document.getElementById("myBar");
let id = setInterval(frame, 1000);
function frame() {
if (percentage >= target) {
clearInterval(id);
} else {
loadingBar.style.width = percentage + "%";
}
}
}
setup();
//moveLoadingbar(); // here is problem
console.log(percentage);
console.log(target);
#myProgress {
width: 100%;
background-color: #ddd;
}
#myBar {
width: 1%;
height: 30px;
background: linear-gradient(90deg, #00C9FF 0%, #92FE9D 100%);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>Progress Bar</h1>
<div id="myProgress">
<div id="myBar"></div>
</div>
<br>
Upvotes: 0
Reputation: 65825
JavaScript processes code synchronously. There is only one thread of execution. The function you pass to setTimeout()
won't be invoked until the JavaScript call stack is idle. So, after you call setTimeout()
, the rest of your code continues to process, all the way down to your console.log()
statements at the bottom, but at that point, your timer callback still hasn't run, so you see its current value (undefined
) logged.
So, really the problem is that your console.log()
statements are running before the asynchronous timer runs. Moving the log into the async function shows you that it's working.
const target = 100; //percent
let percentage;
function setup() {
//Set the start point for today at 09:00:00am
let start = new Date();
start.setHours(9, 00, 00);
setInterval(timeConversion, 1000);
function timeConversion() {
//Work out the difference in miliseconds from now to the start point.
let now = new Date();
let distance = now -= start;
// Time calculations for hours, minutes and seconds
let hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
let seconds = Math.floor((distance % (1000 * 60)) / 1000);
let miliseconds = distance;
//Percentage of day complete **** struggling to pass variable to global variable ****
percentage = (miliseconds / target) * 100;
console.log('p',percentage); // <-- You have to wait until the function has run
}
}
function moveLoadingBar() {
let loadingBar = document.getElementById("myBar");
let id = setInterval(frame, 1000);
function frame() {
if (percentage >= target) {
clearInterval(id);
} else {
loadingBar.style.width = percentage + "%";
}
}
}
//debugging
setup();
moveLoadingBar();
console.log(target);
#myProgress {
width: 100%;
background-color: #ddd;
}
#myBar {
width: 1%;
height: 30px;
background: linear-gradient(90deg, #00C9FF 0%, #92FE9D 100%);
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="stylesheet.css">
<title>Hello world</title>
</head>
<body>
<h1>Progress Bar</h1>
<div id="myProgress">
<div id="myBar"></div>
</div>
<br>
</body>
<script src="index.js"></script>
</html>
Upvotes: 3