How to create a progress timer based on two dates in javascript - javascript

My goal is to create a progress bar that shows a countdown in seconds between one Javascript date and one MYSQL date. So far I have the dates and can subtract them, but I can't get a value that works in seconds for the progress bar. here is my code. Creation date is from a MYSQL datetime.
JAVASCRIPT
$(document).ready(function(){
var deadline= new Date(Date.parse("<? echo $creation_date; ?>"));
var x = setInterval(function() {
var now = Date.now();
var timeleft = deadline - now;
if (timeleft < 0) {
clearInterval(x);
timeleft = 0;
}, 1000);
// draw the bar
function progress(timeleft, timetotal, $element) {
var progressBarWidth = timeleft * $element.width() / timetotal;
$element.find('div').animate({ width: progressBarWidth }, timeleft == timetotal ? 0 : 1000, 'linear');
if(timeleft > 0) {
setTimeout(function() {
progress(timeleft - 1, timetotal, $element);
}, 1000);
}
};
// 86400 is 24 hours.
progress(timeleft, 86400, $('#timerBar'));
HTML
<div id="timerBar">
<div>Time Left</div>
</div>
CSS
#timerBar {
width: 90%;
margin: 10px auto;
height: 30px;
background-color: #efd0d0;
}
#timerBar div {
height: 100%;
text-align: right;
padding: 0 30px;
line-height: 22px;
width: 0;
background-color: #d05656;
box-sizing: border-box;
}

Related

How to add timer inside the progress bar

I want to add a timer which decrease Automatically (like 10 seconds, 9 seconds... till 0 seconds) but the progress bar will increase. And I am new to javascript, and the below code also copied from another site , so please help me in adding timer inside the progress bar
Till now I did this code
I want to make like this
Demo
<div class="progress"></div>
<style>
.progress-bar {
height: 20px;
background: #1da1f2;
box-shadow: 2px 14px 15px -7px rgba(30, 166, 250, 0.36);
border-radius: 50px;
transition: all 0.5s;
}
.progress {
width: 100%;
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: start;
background: #e6e9ff;
border-radius: 20px;
box-shadow: 0px 10px 50px #abb7e9;
}
</style>
<script>
/*
* (class)Progress<nowValue, minValue, maxValue>
*/
//helper function-> return <DOMelement>
function elt(type, prop, ...childrens) {
let elem = document.createElement(type);
if (prop) Object.assign(elem, prop);
for (let child of childrens) {
if (typeof child == "string") elem.appendChild(document.createTextNode(child));
else elem.appendChild(elem);
}
return elem;
}
//Progress class
class Progress {
constructor(now, min, max, options) {
this.dom = elt("div", {
className: "progress-bar"
});
this.min = min;
this.max = max;
this.intervalCode = 0;
this.now = now;
this.syncState();
if(options.parent){
document.querySelector(options.parent).appendChild(this.dom);
}
else document.body.appendChild(this.dom)
}
syncState() {
this.dom.style.width = this.now + "%";
}
startTo(step, time) {
if (this.intervalCode !== 0) return;
this.intervalCode = setInterval(() => {
console.log("sss")
if (this.now + step > this.max) {
this.now = this.max;
this.syncState();
clearInterval(this.interval);
this.intervalCode = 0;
return;
}
this.now += step;
this.syncState()
}, time)
}
end() {
this.now = this.max;
clearInterval(this.intervalCode);
this.intervalCode = 0;
this.syncState();
}
}
let pb = new Progress(15, 0, 100, {parent : ".progress"});
//arg1 -> step length
//arg2 -> time(ms)
pb.startTo(5, 500);
//end to progress after 5s
setTimeout( () => {
pb.end()
}, 10000)
</script>
I think the core problem is that the code you copied is overly complicated especially for beginners. What I would recommend is to start from what you know and build up.
Here is the functionality you want written using only core principles of JavaScript and CSS.
let initialTime = 10; //All time in seconds
let timeLeft = initialTime;
let interval;
let progressBarTextElement = document.getElementById('progress-bar-text');
let progressBarElement = document.getElementById('progress-bar');
function render() {
let progressPercentage = (1 - (timeLeft / initialTime) ) * 100;
progressBarElement.style.width = progressPercentage + '%';
progressBarTextElement.innerHTML = timeLeft + 's';
}
function tick() {
timeLeft = timeLeft - 1;
if(timeLeft <= 0) {
clearInterval(interval); //Stops interval
}
render(); //Updates html
}
function startProgressBar() {
interval = setInterval(tick, 1000); //Will call tick every second
render();
}
startProgressBar();
html {font-family: -apple-system,BlinkMacSystemFont,"Segoe UI","Roboto","Oxygen","Ubuntu","Cantarell","Fira Sans","Droid Sans","Helvetica Neue",sans-serif;}
.progress-bar-continer {
height: 80px;
width: 100%;
position: relative;
display: flex;
justify-content: center;
align-items: center;
background-color: #406086;
}
.progress-bar {
background-color: #1b3e80;
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: 0%;
transition: width 1s; /* Makes progressBar smooth */
transition-timing-function: linear; /* Try to remove this line for more tick tock feel */
}
.progress-bar-text {
color: white;
font-size: 24px;
font-weight: 700;
position: relative;
z-index: 1;
}
<div class="progress-bar-continer">
<div class="progress-bar" id="progress-bar"></div>
<div class="progress-bar-text" id="progress-bar-text"></div>
<div>
Try to understand the code best you can and you will have no problems adding any features you want on top of it. All the fancy stuff will come later with experience.

Can't get 'setTimeout' to delay with random time [duplicate]

This question already has answers here:
Calling functions with setTimeout()
(6 answers)
Closed 2 years ago.
I found a great countdown-timer which counts down to every full minute on the clock and have paired it with a progress bar to better visualize the remaining time. When time is up (=the countdown reaches 1 second) it triggers a certain button press.
However I would like to add a random 0-10 seconds before it calls the button press. I have followed this, this and this post, but can't seem to get it to work. What am I missing?
Here's my code so far:
//timer
setInterval(function () {
var d = new Date();
var seconds = d.getMinutes() * 60 + d.getSeconds(); //convet 00:00 to seconds for easier caculation
var totaltime = 60 * 1; //five minutes is 300 seconds!
var timeleft = totaltime - seconds % totaltime; // let's say 01:30, then current seconds is 90, 90%300 = 90, then 300-90 = 210. That's the time left!
var result = parseInt(timeleft / 60) + ':' + timeleft % 60; //formart seconds into 00:00
document.getElementById('countdown_timer').innerHTML = result;
//progressbar
function progress(timeleft, timetotal, $element) {
var progressBarWidth = (timetotal - timeleft) * ($element.width() / timetotal);
$element.find('div').animate({
width: progressBarWidth
}, "linear");
}
progress(timeleft, totaltime, $('#progress_bar'));
if (timeleft == 1) {
setTimeout (document.getElementById('next_btn').click(), Random () );
function Random() { //randomgenerator
var min = 0;
var max = 10;
var random = Math.floor(Math.random() * (max - min + 1) + min);
// document.getElementById('randomNumber').value = random;
// setTimeout(function() {document.getElementById('next_btn').click();},random)
}
}
}, 1000)
#progress_bar {
box-sizing: border-box;
width: 95%;
height: 26px;
bottom: 22px;
left: 50%;
transform: translate(-50%);
position: fixed;
background-color: #1D789F;
border-radius: 8px;
z-index: 2;
}
#progress_bar div {
height: 100%;
line-height: 23px; /* same as #progressBar height if we want text middle aligned */
width: 0;
border-radius: 8px;
background-color: #A05336;
}
#countdown_timer {
position: fixed;
bottom: 15px;
left: 15%;
z-index: 3;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="progress_bar">
<div></div></div>
<div id="countdown_timer"></div>
</div>
The second argument to setTimeout is the number of milliseconds to delay before the function runs. Your current Random function returns a number between 0 and 10; a delay of 0ms is indistinguishable from a delay of 10ms.
Multiply the result by 1000 before passing to setTimeout.
setTimeout (() => document.getElementById('next_btn').click(), 1000 * Random() );
You also need to pass a function to setTimeout (a function that, when invoked, clicks), instead of invoking the .click immediately.
//timer
setInterval(function () {
var d = new Date();
var seconds = d.getMinutes() * 60 + d.getSeconds(); //convet 00:00 to seconds for easier caculation
var totaltime = 60 * 1; //five minutes is 300 seconds!
var timeleft = totaltime - seconds % totaltime; // let's say 01:30, then current seconds is 90, 90%300 = 90, then 300-90 = 210. That's the time left!
var result = parseInt(timeleft / 60) + ':' + timeleft % 60; //formart seconds into 00:00
document.getElementById('countdown_timer').innerHTML = result;
//progressbar
function progress(timeleft, timetotal, $element) {
var progressBarWidth = (timetotal - timeleft) * ($element.width() / timetotal);
$element.find('div').animate({
width: progressBarWidth
}, "linear");
}
progress(timeleft, totaltime, $('#progress_bar'));
if (timeleft == 1) {
setTimeout( () => { document.getElementById('next_btn').click(); }, 1000 * Random() );
function Random() { //randomgenerator
var min = 0;
var max = 10;
var random = Math.floor(Math.random() * (max - min + 1) + min);
// document.getElementById('randomNumber').value = random;
// setTimeout(function() {document.getElementById('next_btn').click();},random)
}
}
}, 1000)
#progress_bar {
box-sizing: border-box;
width: 95%;
height: 26px;
bottom: 22px;
left: 50%;
transform: translate(-50%);
position: fixed;
background-color: #1D789F;
border-radius: 8px;
z-index: 2;
}
#progress_bar div {
height: 100%;
line-height: 23px; /* same as #progressBar height if we want text middle aligned */
width: 0;
border-radius: 8px;
background-color: #A05336;
}
#countdown_timer {
position: fixed;
bottom: 15px;
left: 15%;
z-index: 3;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="progress_bar">
<div></div></div>
<div id="countdown_timer"></div>
</div>

Dynamically change animation speed

For teaching myself javascript (and for getting/giving more insight in the field of astronomy :) ), I am setting up a page that displays relative positions of sun and moon.
Right now, the speed of the sun and moon movement is still fixed, but I would really like to make this dynamically user-definable via an input field. So, the initial speed is '30', and a user can speed this up or slow this down. Obviously, the ratio between sun and moon must stay fixed. I tried a lot of things (see some relics in the code, but I can't get it to work.
Anyone with more experience with javascript can assist me in doing this? Also, I notice CPU usage gets very high during this animation. Are there simple steps in making this script more efficient?
var dagen = 0;
function speed($this){
var speedSetting = $this.value;
//alert(speedSetting);
//return per;
}
function periode(bolletje, multiplier=30){
if (bolletje == 'zon'){var per = (multiplier*24/2);}
if (bolletje == 'maan'){var per = (multiplier*24*29.5/2);}
return per;
}
function step(delta) {
elem.style.height = 100*delta + '%'
}
function animate(opts) {
var start = new Date
var id = setInterval(function() {
var timePassed = new Date - start
var progress = timePassed / opts.duration
if (progress > 1) progress = 1
var delta = opts.delta(progress)
opts.step(delta)
if (progress == 1) {
clearInterval(id)
}
}, opts.delay || 10)
}
function terugweg(element, delta, duration) {
var to = -300;
var bolletje = element.getAttribute('id');
per = periode(bolletje);
document.getElementById(bolletje).style.background='transparent';
animate({
delay: 0,
duration: duration || per,
//1 sec by default
delta: delta,
step: function(delta) {
element.style.left = ((to*delta)+300) + "px"
}
});
if(bolletje == 'zon'){
dagen ++;
}
bolletje = element;
document.getElementById('dagen').innerHTML = dagen;
//setInterval(function (element) {
setTimeout(function (element) {
move(bolletje, function(p) {return p})
}, per);
}
function move(element, delta, duration) {
var to = 300;
var bolletje = element.getAttribute('id');
per = periode(bolletje);
document.getElementById(bolletje).style.background='yellow';
animate({
delay: 0,
duration: duration || per,
//1 sec by default
delta: delta,
step: function(delta) {
element.style.left = to*delta + "px"
}
});
bolletje = element;
//setInterval(function (element) {
setTimeout(function (element) {
terugweg(bolletje, function(p) {return p})
}, per);
}
hr{clear: both;}
form{display: block;}
form label{width: 300px; float: left; clear: both;}
form input{float: right;}
.aarde{width: 300px; height: 300px; border-radius: 150px; background: url('https://domain.com/img/aarde.png');}
#zon{width: 40px; height: 40px; background: yellow; border: 2px solid yellow; border-radius: 20px; position: relative; margin-left: -20px; top: 120px;}
#maan{width: 30px; height: 30px; background: yellow; border: 2px solid yellow; border-radius: 16px; position: relative; margin-left: -15px; top: 115px;}
<form>
<div onclick="move(this.children[0], function(p) {return p}), move(this.children[1], function(p) {return p})" class="aarde">
<div id="zon"></div>
<div id="maan"></div>
</div>
Dagen: <span id="dagen">0</span>
</form>
<form>
<label><input id="snelheid" type="range" min="10" max="300" value="30" oninput="speed(this)">Snelheid: <span id="snelheidDisplay">30</span></label>
</form>
First, change onlick to oninput in speed input tag.
<input id="snelheid" type="number" value="30" oninput="speed(this)">
And in your speed() function set multiplier = $this.value. multiplier should be global:
var multiplier = 30;
function speed($this){
console.log($this.value);
multiplier = $this.value;
//alert(speedSetting);
//return per;
}
function periode(bolletje){
if (bolletje == 'zon'){var per = (multiplier*24/2);}
if (bolletje == 'maan'){var per = (multiplier*24*29.5/2);}
return per;
}
Here is an example:
https://jsfiddle.net/do4n9L03/2/
Note: multiplier is not speed, it is delay. If you increase it it become slower

Logout with a countdown progress bar

I am using the code from here to logout users after idle time (when no click is received anywhere on the body). I am trying to combine that with a countdown progress bar here
My Code below
#timeouts {
display: none;
}
#progressBar {
width: 100%;
margin: 10px auto;
height: 22px;
background-color: red;
}
#progressBar div {
height: 100%;
text-align: right;
padding: 0 10px;
line-height: 22px; /* same as #progressBar height if we want text middle aligned */
width: 0;
background-color: yellow;
box-sizing: border-box;
}
HTML
<body class="smoothscroll boxed pattern7 printable" onload="StartTimers();" onclick="ResetTimers();">
<div id="progressBar"><div></div></div>
<div id="timeouts">
<h2>Session About To Timeout</h2>
<span class="alert alert-warning">Alert! Logout in 4 Seconds</span>
</div>
</body>
JS
var timoutWarning = 10000; // Displa
var timoutNow = 14000; // Time
var logoutUrl = '/logout'; //
var warningTimer;
var timeoutTimer;
// Start timers.
function StartTimers() {
warningTimer = setTimeout("IdleWarning()", timoutWarning);
timeoutTimer = setTimeout("IdleTimeout()", timoutNow);
}
// Reset timers.
function ResetTimers() {
clearTimeout(warningTimer);
clearTimeout(timeoutTimer);
StartTimers();
document.getElementById("timeouts").style.display = "none";
progress(14, 14, $('#progressBar')); //This makes things go crazy
}
// Show idl
function IdleWarning() {
document.getElementById("timeouts").style.display = "block";
}
// Logout the user.
function IdleTimeout() {
window.location = logoutUrl;
}
function progress(timeleft, timetotal, $element) {
var progressBarWidth = timeleft * $element.width() / timetotal;
$element.find('div').animate({ width: progressBarWidth }, timeleft == timetotal ? 0 : 1000, 'linear').html(timeleft+ " s");
if (timeleft > 0) {
setTimeout(function () {
progress(timeleft - 1, timetotal, $element);
}, 1000);
}
};
progress(14, 14, $('#progressBar'));
It will work perfectly on page load. But when the function ResetTimers() is called, it is supposed to reset the progress function. But things go crazy with the progress bar showing random values. Please help me figure out what is going on.
I solved it like this.
var timoutWarning = 1140000; // Display warning after 19 minutes
var logoutUrl = '/logout'; //
var warningTimer;
var timeoutTimer;
var progressTimer;
var timeleft = 1200;
var timetotal = 1200;
// Start timers.
function StartTimers() {
warningTimer = setTimeout("IdleWarning()", timoutWarning);
progress(timeleft, timetotal, $('#progressBar'));
}
// Reset timers.
function ResetTimers() {
clearTimeout(warningTimer);
clearTimeout(progressTimer);
StartTimers();
document.getElementById("timeouts").style.display = "none";
}
// Show idl
function IdleWarning() {
document.getElementById("timeouts").style.display = "block";
}
// Logout the user.
function IdleTimeout() {
window.location = logoutUrl;
}
function progress(timeleft, timetotal, $element) {
var progressBarWidth = timeleft * 100 / timetotal;
$element.find('div').animate({ width: progressBarWidth }, timeleft == timetotal ? 0 : 1000, 'linear').html((timeleft / 60).toFixed(1) + " m");
if (timeleft > 0) {
progressTimer = setTimeout(function () { progress(timeleft - 1, timetotal, $element); }, 1000);
}
else {
IdleTimeout();
}
};
By assigning a variable to the setTimeout function call inside my recursive function and then clear it by clearTimeout(progressTimer) inside the ResetTimers() call. Thank you

Delay until fully loaded

There's a clock in my page that loads pretty fast but there's an instant when it loads where you can see it stopped. I want to make it appear only when it's fully loaded.
This is the code of the clock:
<style type="text/css">
* {
margin: 0;
padding: 0;
}
#clock {
position: relative;
width: 500px;
height: 480px;
background: url(images/clockface.png);
list-style: none;
}
#sec, #min, #hour {
position: absolute;
width: 30px;
height: 600px;
top: 0px;
left: 225px;
}
#sec {
background: url(images/sechand.png);
z-index: 3;
}
#min {
background: url(images/minhand.png);
z-index: 2;
}
#hour {
background: url(images/hourhand.png);
z-index: 1;
}
p {
text-align: center;
padding: 10px 0 0 0;
}
</style>
<script type="text/javascript">
$(document).ready(function() {
setInterval( function() {
var seconds = new Date().getSeconds();
var sdegree = seconds * 6;
var srotate = "rotate(" + sdegree + "deg)";
$("#sec").css({"-moz-transform" : srotate, "-webkit-transform" : srotate});
}, 1000 );
setInterval( function() {
var hours = new Date().getHours();
var mins = new Date().getMinutes();
var hdegree = hours * 30 + (mins / 2);
var hrotate = "rotate(" + hdegree + "deg)";
$("#hour").css({"-moz-transform" : hrotate, "-webkit-transform" : hrotate});
}, 1000 );
setInterval( function() {
var mins = new Date().getMinutes();
var mdegree = mins * 6;
var mrotate = "rotate(" + mdegree + "deg)";
$("#min").css({"-moz-transform" : mrotate, "-webkit-transform" : mrotate});
}, 1000 );
});
</script>
Thanks
<ul id="clock" style="visibility: hidden"> <!-- this is so the browser computes the position of the element but doesn't show it just yet -->
<li id="sec"></li>
<li id="hour"></li>
<li id="min"></li>
</ul>
Then:
<script type="text/javascript">
window.onload = function() { // this will be run when the whole page is loaded
document.getElementById("clock").style.visibility = "display";
};
</script>
A div does not have a load event.
On DOM ready, I would hide the clock...
document.getElementById("clock").style.display = 'none';
...and then at the end of the code of the clock, when it is finished, I would set its display to block...
document.getElementById("clock").style.display = 'block';
...or inline if that is more appropriate in your situation.

Categories

Resources