javascript Bootstrap Progressbar fill in 10 seconds - javascript

I have a Progressbar in Bootstrap that fills every 1 sec 10% of the progressbar.
The problem is, that the site lags over the whole browser (chrome), but why?
That's my code that fills the Progressbar
var isPaused = false;
$(window).scroll(function(){
var ScrollTop = parseInt($(window).scrollTop());
if (ScrollTop > 10) {
isPaused = true;
} else {
isPaused = false;
}
});
var timeleft = 1;
var table_updated = 0;
var timeleft_zahl = 10;
var tick = function() {
if(!isPaused && $("#page-1").hasClass("active") && !$(".modal").hasClass("show")) {
document.getElementById("progressBar").style.width = timeleft*10+"%";
document.getElementById("refreshcountdown").innerHTML = timeleft_zahl-1;
timeleft += 1;
timeleft_zahl -= 1;
if(timeleft >= 11){
notificationcheck();
timeleft = 0;
timeleft_zahl = 11;
if(table_updated >= 10) {
location.reload();
table_updated = 0;
} else {
get_table_data(1);
table_updated += 1;
}
}
}
}
timer = setInterval(tick, 1000);
So it's just simple.
I have a few options, like isPaused and some other things that stops the progressbar filling, cause when user scroll, than it must stop.
But why does it lag? the Interval runs every 1000 (so 1 sec) to fill every 1 sec 10% if isPaused false and the other if things are correct

Your tick function is called every second, thus only every second there is a decision whether to increase the progress bar or not.
I guess the "lags" you discover are just imaginary because your scrolling will never take an exact amount of seconds like 1, 3 or 5 seconds but something like 1.4 or 3.8 seconds. Thus, you think the increase of your progress bar is delayed because it takes some milliseconds until the tick function is called again.
To avoid this effect you could add a listener that fires when no scrolling is performed (in other words, when the scroll stops). In that case you should reset the setInterval function.

Related

setInterval goes to negative

I'm buidling this pomodoro app.
https://jsfiddle.net/yvrs1e35/
I got few problems with the timer.
startBtn.addEventListener('click', function(){
minutes.innerHTML = sessionTime.innerHTML - 1
seconds.innerHTML = 59
var timer = setInterval(()=>{
if(Number(minutes.innerHTML) != 0 && Number(seconds.innerHTML) != 0){
seconds.innerHTML--
if(Number(seconds.innerHTML) == 0){
seconds.innerHTML = 59;
minutes.innerHTML--
}
}else if (Number(minutes.innerHTML) == 0 && Number(seconds.innerHTML) == 0){
clearInterval(timer)
}
},1000)
resetBtn.addEventListener('click', function(e){
e.preventDefault();
breakTime.innerHTML = 5
sessionTime.innerHTML = 25
minutes.innerHTML = "00"
seconds.innerHTML = "00"
clearInterval(timer)
})
pauseBtn.addEventListener('click', function(e){
e.preventDefault();
})
})
It works if the timer if there is more than 1 minute left on the interval.
If it goes under 1 minute, even though i have this if in the interval
else if (Number(minutes.innerHTML) == 0 && Number(seconds.innerHTML) == 0){
clearInterval(timer)
}
seconds and minutes go on negative ( after 0:0, timer shows -1:59)
I though that else if statement would stop the interval when both minutes and seconds reach 0, but it doesnt for some reason.
#also if i press startbtn multiple times, the timer starts multiple times, and the seconds go 2x 3x 4x faster, how can I stop the startbtn until the timer reaches 0:0?
Can i get any help?
.innerHTML is an expensive operation. Storing data inside the DOM like this is an antipattern; extracting it and manipulating it stringifies and de-stringifies numbers for no reason. Store state in your JS script and update the DOM content only when a rendering change is necessary. In other words, consider it write-only.
The interval runs multiple times; you'll need a flag to prevent re-triggers (or clearInterval before resetting it). Setting interval to undefined is a good way to indicate that the clock isn't running.
Lastly, setInterval with a cooldown of 1000 is a poor choice for timekeeping. It will drift quite a bit depending on scheduling interruptions and other random factors; the 1000 means "wait at least 1000 milliseconds before firing the callback". Instead, use Date for accuracy.
I'd work entirely in milliseconds and convert to minutes and seconds only for the formatted output. This follows the principle described in the first paragraph about separating presentation from logic.
Here's a proof of concept to illustrate the above points. Of course, if you're doing the pomodoro for fun, sticking to setInterval(() => ..., 1000) does make the code simpler, but I think it's instructive to see it from a couple angles if nothing else.
const padTime = t => (Math.floor(t) + "").padStart(2, 0);
const timeFmt = t => `${padTime(t / 60000)}:${
padTime(t / 1000 % 60)}`;
const run = () => {
interval = setInterval(() => {
if (interval) {
display.textContent = timeFmt(end - Date.now());
}
if (Date.now() >= end) {
clearInterval(interval);
interval = undefined;
}
}, 100);
};
let interval;
let pause;
const initialMinutes = 2;
const duration = initialMinutes * 60000;
const time = Date.now();
let end = time + duration;
const display = document.querySelector("h1");
display.textContent = timeFmt(end - time);
const [startBtn, pauseBtn, resetBtn] =
document.querySelectorAll("button");
startBtn.addEventListener("click", e => {
clearInterval(interval);
if (!interval) {
if (pause) {
end += Date.now() - pause;
pause = undefined;
}
else {
end = Date.now() + duration;
}
}
run();
});
resetBtn.addEventListener("click", e => {
clearInterval(interval);
interval = undefined;
const time = Date.now();
end = time + duration;
display.textContent = timeFmt(end - time);
});
pauseBtn.addEventListener("click", e => {
if (interval) {
pause = Date.now();
clearInterval(interval);
interval = undefined;
}
});
<h1></h1>
<div>
<button>start</button>
<button>pause</button>
<button>reset</button>
</div>
if(Number(minutes.innerHTML) != 0 && Number(seconds.innerHTML) != 0)
Changing the "&&" to "||" should fix one problem (which is that it is stuck at 0:59). If you add another condition to
if(Number(seconds.innerHTML) == 0){
where the if condition is only true, if seconds == 0 AND minutes > 0, then all problems should be solved.
Your negative time comes from starting at 0 and because of this:
minutes.innerHTML = sessionTime.innerHTML - 1
seconds.innerHTML = 59
It changes minutes to negative value and sets seconds to 59. You should add some validation before this and don't start clock.
setInterval doesn't guarantee that your function will execute in the precise interval, just that it wouldn't execute earlier. This way, on a slow/loaded computer, the function could be called after the interval is already elapsed.
In other words, you probably wish to check if the timer has already elapsed, not if it's just about to do so.
(Number(minutes.innerHTML) <= 0 && Number(seconds.innerHTML) <= 0)

How to make the timer tickle each second and make it jump when video is forwarded or rewinded?

I am trying to make a timer which indirectly syncs with the video. When starttimer is clicked, it should starts my timer and tickle each second.
Here is the process:
1. Start the video
2. At a certain time in video, click to start the timer
3. Timer starts from 00:00:00 and should tickle each second.
4. If the video is forwarded by `n` seconds timer should be 'timer+n` seconds. Same for the case, when video is rewinded - `timer-n'
But my timer, is not functioning properly. It works fine, when I start the timer but when I forward by n seconds, it sometimes goes by n and sometimes by n+1 or n+2 and when I rewind by n it goes back at its own will.
I just cannot get the logic correct.
Called when starttimer is clicked: (It starts the clock from 00:00:00)
var mtimer = 0;
$('#starttimer').click(function() { // Starts the clock
playing = true;
if(!timerstarted) {
setInterval(function() {
if(playing) {
mtimer++;
$('#starttimer').html(getHHMMSS(mtimer));
}
} , 1000 );
timerstarted = true;
}
});
When video is forwarded or rewinded: (I also have a control, wherein I could move the video forward by 3 seconds or back by 3 seconds by pressing shift+r and shift+l. I hope it is equivalent to seeking)
var lastCurrentTime = 0;
$('#match').on('seeking',function(event) {
var difference = 0;
var newCurrentTime = $('#match').get(0).currentTime;
if(newCurrentTime > lastCurrentTime) {
difference = newCurrentTime - lastCurrentTime;
playing = false;
mtimer = mtimer + difference;
$('#starttimer').html(getHHMMSS(mtimer));
playing = true;
}else {
difference = lastCurrentTime - newCurrentTime;
playing = false;
mtimer = mtimer - difference;
console.log("Difference : " + difference);
playing = true;
if(mtimer <= 0) {
mtimer = 0;
$('#starttimer').html(getHHMMSS(mtimer));
}
}
lastCurrentTime = newCurrentTime;
});
Set the offfset
Use offset for moving mtimer back and forth
clearinterval when seeking
starttimer function:
$('#starttimer').click(function() { // Starts the clock
playing = true;
if(!timerstarted) {
offset = $('#match').get(0).currentTime;
timerv = setInterval(function() {
var newCurrentTime = $('#match').get(0).currentTime;
if(playing) {
mtimer++;
$('#starttimer').html(getHHMMSS(mtimer));
}
//$('#starttimer').html(getHHMMSS(mtimer));
} , 1000 );
timerstarted = true;
}
});
seeking function:
$('#match').on('seeking',function(event) {
playing = true;
if(timerstarted) {
clearInterval(timerv);
var newCurrentTime = $('#match').get(0).currentTime;
mtimer = newCurrentTime - offset;
if(mtimer < 0) {
mtimer = 0;
offset = 0;
$('#starttimer').html(getHHMMSS(mtimer));
console.log("playing : " + playing);
}
timerv = setInterval(function() {
if(playing) {
console.log("Inside playing...");
mtimer++;
$('#starttimer').html(getHHMMSS(mtimer));
}
/*if(playing) {
if(timerset === true && $('#timeentered').val() !== '') {
mtimer = $('#timeentered').val();
timerset = false;
}
mtimer++;
}*/
//$('#starttimer').html(getHHMMSS(mtimer));
} , 1000 );
lastCurrentTime = newCurrentTime;
}
});
You need to sync your two timer variables when you start the timer. The mtimer variable starts counting the seconds when you start the timer, but lastCurrentTime is set to zero until the first time you 'seek' the video one direction or another. This is going to throw the timing off.
Let's say you start the timer one minute into the video. Once you have watched the video for a minute, mtimer is at 60 seconds, the video timer is at 120 seconds, and lastCurrentTime is still at zero. If I roll the video back by 90 seconds, mtimer should go negative by thirty seconds, but, based on your code, mtimer will be set to positive 30.
Try this:
var mtimer = 0;
var lastCurrentTime = 0;
$('#starttimer').click(function() { // Starts the clock
playing = true;
if(!timerstarted) {
//Set the timer before starting the interval
//Gives you one second with the timer at zero before the first interval runs
$('#starttimer').html(getHHMMSS(mtimer));
//Set lastCurrentTime to the video time.
lastCurrentTime = $('#match').get(0).currentTime;
setInterval(function() {
if(playing) {
//Keeps both timers synched as the movie plays.
mtimer++;
lastCurrentTime++;
$('#starttimer').html(getHHMMSS(mtimer));
}
} , 1000 );
timerstarted = true;
}
});
Now, your current seeking function should work. If the newCurrentTime is larger than the lastCurrentTime, mtimer will be advanced by the difference. If the opposite is true, then mtimer will be reduced by the difference. In the case I mentioned above, when mtimer should have gone negative by thirty seconds, mtimer would be set to zero. Based on your code, I'm assuming you want the timer reset if mtimer goes below zero.
Hope this fits your needs.

How to speed up the count down?

I am working on a basic countdown using Javascript where, the countdown starts from 0 and then ends till 24 as thats the idea of the countdown, I want to end it at 24. Here's the code:
var count=0;
var counter=setInterval(timer, 50); //1000 will run it every 1 second
function timer()
{
count=count+1;
if (count >= 24)
{
clearInterval(counter);
//counter ended, do something here
document.getElementById("countdown").innerHTML=24 ;
return;
}
//Do code for showing the number of seconds here
document.getElementById("countdown").innerHTML=count ; // watch for spelling
}
Now the thing is that if you notice this, the countdown happens very fast, this is the intended effect. However the question is this, Is there a way to have a smooth easing type effect, where the countdown starts slowly and then speeds up by the end ? How to achieve that effect ?
Thanks for your response.
EDIT: Here is the fiddle, to see the countdown in action and to gain a deeper insight.
You'll need to use setTimeout instead of setInterval and another variable for setTimeout.
var count=0;
var speed = 1000;
timer();
function timer()
{
count++;
//Do code for showing the number of seconds here
document.getElementById("countdown").innerHTML=count ; // watch for spelling
if (count >= 24)
{
return;
}
speed = speed / 6 * 5; // or whatever
setTimeout(timer, speed);
}
Fiddle: http://jsfiddle.net/4nnms1gz/2/
Use a timeout which runs only once then add extra time and run the timeout again until you reach 24.
var count=0;
var ms = 200;
var step = 5;
var counter=setTimeout(timer, ms); //1000 will run it every 1 second
function timer()
{
count=count+1;
if (count <= 24)
{
//Do code for showing the number of seconds here
document.getElementById("countdown").innerHTML=count ; // watch for spelling
ms = ms - step;
counter = setTimeout(timer, ms);
}
}
Using setTimeout will give you more control on your counter.Here is a working example where you can handle the speed of your counter.It will give you a time increase of 30ms to 70ms to each call to time function
var count=0;
var loop=1000;
var interval;
var text=document.getElementById('countdown');
var range=document.getElementById('range');
var btn=document.getElementById('btn');
var span=document.getElementById('val');
range.addEventListener('change',function(e){
span.innerHTML=range.value+' ms';
});
btn.addEventListener('click',function(e){
timer(parseInt(range.value));
});
function timer(time)
{
console.log(time);
if (count < 24)
{
count=count+1;
text.value=count;
loop-=time;
interval=setTimeout(function(){
timer(time);
},loop);
if(count>=24){
clearTimeout(interval);
return;
}
}
}
<input type='text' id='countdown' value='0'></br>
<input type='range' id='range' max='70' min='30' value='30' >increase by:<span id='val'></span></br>
<input type='button' value='start' id='btn' ></br>

Implementing a timer app in Metro App

I am developing a game in Metro app where there would be an initial timer for the game to run, let's say about 1 minute and 50 seconds and the timer is displaying the current time. if the 1 minute and 50 seconds time is over, the game will be over it will show a message, How would I implement such behaviour?
I would say, you can try this (untested):
remainingTime = 110;
setInterval(function() {
countdownStarted(); // game started
},
milliseconds // game will start in this much time
);
function countdownStarted() {
setInterval(function() {
remainingTime = remainingTime*100;
updateTimeOnScreen(); // after every second
if(remainingTime) countdownStarted();
},
100
);
}
function updateTimeOnScreen() {
if(remainingTime == 0) {
timeUp(); // game over
}
// function continues
}
For more examples, I would suggest you to read this article.
This basically does the trick, though this is the only thing my app does, so your real performance might vary and there are likely other improvements, stylistic and otherwise, you can make:
var timer = setInterval(function () {
var div = document.getElementById('time'); // this is just a div
// the div shows the time like this: "1:20" - 1 minute, 20 seconds
var lastValue = div.innerText.split(':');
var newValue = parseInt(lastValue[0]) * 60 + parseInt(lastValue[1]) + 1;
if (newValue === 110) {
div.innerText = "Game over!";
clearInterval(timer);
} else {
div.innerText = Math.floor(newValue / 60) + ':' + newValue % 60;
}
}, 1000);
For something more robust, check out this article. It looks like it's pretty close to what you want to do.
You can create an object that has a setTimeout and clearTimeout methods set to some user-defined value.
This link can also give you some useful info.

Timer counting faster on second run

I am working on a simple game right now. its almost done except for the timer has a glitch in it and I can't figure out whats doing it. when you push a button, an HTML5 text on the canvas starts to count down from 35 to 0. On the first run it's fine. But if you choose to play again with out refresh the timer starts to countdown faster. here is the code.
var timer = 35;
ctx.fillText("Countdown: " + timer, 320, 32);
function resetReggie(){
reggie.x = canvasWidth / 2;
reggie.y = canvasHeight / 2;
}
//Starts Timer for Timed Game
function timedMsg()
{
resetReggie();
ballsCaught = 0;
timer = 35;
alert('Pick up as many as you can in ' + timer + ' seconds');
countDown();
var t=setTimeout(function() {
var again = confirm("TIMES UP! You Gathered " + ballsCaught + " Balls! Play Again?");
if (again === true){
timedMsg();
resetReggie();
}
if (again === false){
resetReggie();
ballsCaught = 0;
timer = 35;
}
}, timer * 1000);
}
function countDown() {
if (timer != 0){
timer-=1;
setTimeout('countDown()', 1000);
}
}
I think the problem is in the line
}, timer * 1000);
where you have a value that is at most 34 at the time 'timer' is evaluated to set the timeout. Because you initialize it to 35 but then call countDown() which decreases it to 34, then you have a call to confirm() which might let 'timer' decrease even more. As a result the subsequent call to timedMsg() happens a little too soon causing countDown() to be called twice as often. Try the following (I ran it in node) and then change the 4 to 6.
function countDown() {
console.log("Countdown: " + timer, 320, 32);
if (timer != 0) {
timer -= 1;
setTimeout(countDown, 1000);
}
}
function timedMsg() {
timer = 5;
countDown();
var t=setTimeout(function() {
timedMsg();
}, 4 * 1000);
}
timedMsg();
As mentioned in my comment, each time you start a new game, it appears you are decreasing the timeout value. As a result, this reduces the time each time.
Try this:
var timeout = currentTime = 5;
var int = setInterval(function() {
​console.log(currentTime);
currentTime--;
if(currentTime < 0) {
var again = confirm('Play again?');
if(again) {
currentTime = timeout;
}
else {
clearInterval(int);
}
}
}, 1000);​
http://jsfiddle.net/gRoberts/CsyYx/
Look at your console (F12 in Chrome), or update the code to write to the browser to see it working ;)

Categories

Resources