Pause a timer in javascript - javascript

I have created a small generic 4 stage pipeline and it simulates for the clock period provided. However i wanted to pause it and resume it in the middle and am not able to do that. This is my FIDDLE and for the pause i thought of adding a flag.
if flag == 1 //keep simulating
if flag == 0 // pause simulation where it is
if flag == 0 and click resume resume simulation until its end
var flag = 1; //initial value
function pause(){
flag = 0;
}
function resume(){
flag = 1;
}
//i try to check if flag is 0 then alert pause or something but no luck
function startSim(){
document.getElementById('clockDiv').innerHTML = 'Clock Period '+clockPeriod;
if(index == 22){
clearInterval(sim);
}else if(flag == 0){
alert("Simulation Paused");
}else{
clockPeriod++;
fetch();
decode();
execute();
store();
index++;
}
}
I would appreciate tips on how to do this.

The problem is not so much your code, but rather how the default way of loading javascript in jsfiddle is working (nl, onload, so an anonymous function)
Therefor your functions pause / resume are no longer available when you click your buttons.
To change this, you can change the way the javascript is loaded inside your page, for you the easiest is:
At this time your code will partly work (alert is very annoying as it pops up at every interval), and your reset won't work because the var sim was defined locally (as #razzak mentioned in another answer)

You should change the JavaScript settings in Fiddler: set "Load Type" to no-wrap and your code will work.
Although I would suggest using clearTimeout instead of flags.

I think thats not just a fiddle issue, look at this:
function start(){
var sim = setInterval(function(){startSim()},500);
}
....
if(index == 22){
clearInterval(sim);
}else if(flag == 0){
alert("Simulation Paused");
....
you re creating sim inside the local scope of the function and then using it inside an other function... this is actually an error.
use this:
function start(){
return setInterval(function(){startSim()},500);
}
FIDDLE

If a user click pause, you setup the flag and handle it in the startSim callback. If flag == 0 you try to simulate pause, but your index counter becomes 22 at 11 secs. It will be clear very fast, before you click pause.

Here is my go: http://jsfiddle.net/j82j14r6/2/
Instead of setInterval, I am using setTimeout and having a function call itself:
function tick()
{
if(!paused)
{
// Do stuff
document.querySelector('#log').value = ticks;
ticks++;
}
setTimeout(tick, 500);
}
This allows for easy control over tickrate, pausing, ending, etc.
Please note that using setTimeout or setInterval is not exactly the most accurate way to calculate time and / or make loops like this, but in case your project is not too important - this is a ok way to do it.
As to why your buttons are not calling the corresponding functions... that is mostly a jsfiddle problem. I fixed this with addEventListener in the JS section, instead of having onclick on the HTML button itself.
<input type = "button" value = "togglepause" id = "pausebutton"/><br/>
document.querySelector('#pausebutton').addEventListener('click', togglepause);

Related

Javascript fire the last event

I'm coding a web application and I don't know how to keep on what I'm trying to do with Javascript.
I have a function that is fired when I do zoom on a map or when I move the map. I try to avoid this function do its stuff until it's been a while (2 seconds, for example). Ok, I can use a setInterval method to achieve it.
But what I want and I don't know how to do is... if I do zoom 3 times, very close in time between them, I just want to process the last zoom, not the two previuos ones. I mean, the 2 first function callings have to be cancelled, or something like that.
How could I do that?
Example (pseudo-code) of what I have:
function doStuff() {
setInterval(function({
// do some stuff here...
}, 2000);
}
myMap.on('dragend', doStuff); // If I move inside the map
myMap.on('zoomend', doStuff); // If I do zoom on the map
What I´d try is to set capture the intervalID in a global varial everytime you start your interval; then when you fire the event you check if the variable is set, if it is, you use the clearInterval function to cancel the previous interval before starting the next one.
Something like this:
var intervalID = 0;
function doStuff(){
if(intervalID != 0){
window.clearInterval(intervalID);
}
intervalID = setInterval(function({
// do some stuff here...
intervalID = 0; // try reseting the intevalID on completion, not sure if here
}, 2000);
// Your stuff
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/clearInterval
You could use a object.addEventListener('load', function())-function.
The function inside it will fire after the object has loaded.

CesiumJS - How can I control viewer time and ticks?

What I'd like to do is control the clock ticks for a non-realtime Cesium application. Imagine there's expensive code running, plus I want to give the viewer time to load the tiles before continuing. So how do I disable automatic ticking, and then call tick() manually when my code is ready for it?
Docs for Cesium.Clock say "The clock will only tick when both Clock#canAnimate and Clock#shouldAnimate are true." but that's not what I'm getting.
What I currently see:
viewer.clock.canAnimate = false;
viewer.clock.shouldAnimate = false;
viewer.clock.onTick.addEventListener(function(clock){
console.log("Tick");
});
The result in the console shows the clock still ticking:
Tick
Tick
Tick
Tick
...
What I'd like to do:
viewer.clock.stopTicking(); // or whatever that command would be...
while (someCondition){
// run expensive code
tick(); // issue manual tick
}
Thanks for your help!
Max
It's a bit of a legacy quirk of the Cesium API that the Clock's onTick event fires for every animation frame rendered, regardless of whether the clock advances in time or not.
If you want to take control of Cesium's render loop yourself, you can do that like this:
viewer.useDefaultRenderLoop = false;
function myOwnRenderLoop() {
viewer.resize();
viewer.render();
Cesium.requestAnimationFrame(myOwnRenderLoop);
}
Cesium.requestAnimationFrame(myOwnRenderLoop);
Above, I'm using requestAnimationFrame, so the loop runs as fast as possible. But I could replace that with setTimeout to get a slower loop, emulating poor render performance. Note that interactivity and screen updates would slow down with such a method when longer time intervals are used.
viewer.useDefaultRenderLoop = false;
function myOwnRenderLoop() {
viewer.resize();
viewer.render();
window.setTimeout(myOwnRenderLoop, 500);
}
window.setTimeout(myOwnRenderLoop, 500);
So, your console.log is still printing 'Tick' because the onTick continues to fire, regardless of whether the clock is advancing. All you need to do is toggle both the canAnimate and shouldAnimate, as you suspected. So, your example code would basically be:
viewer.clock.canAnimate = false;
viewer.clock.shouldAnimate = false;
while (someCondition){
// run expensive code
// toggle someCondition so we can exit this
}
// set the animate bools back to true so the clock can advance
viewer.clock.canAnimate = true;
viewer.clock.shouldAnimate = true;
To better see this in action, try this (and maybe set the if conditional to 1000 instead of 100):
viewer.clock.canAnimate = false;
viewer.clock.shouldAnimate = false;
var s = 0;
viewer.clock.onTick.addEventListener(function(clock){
if (s < 100) {
console.log(viewer.clock.currentTime);
} else {
viewer.clock.canAnimate = true;
viewer.clock.shouldAnimate = true;
}
s++;
});
You'll see that the console.log is printing the same value for 100 (or 1000) times...this is because the currentTime isn't advancing because of the canAnimate and shouldAnimate. Once those are both toggled back to true, the currentTime will advance.

Call function when <audio> is at specific time

I am currently doing some fun website, which requires audio cues (I assume that's the name?). I want the site to do something, when the song has been played for exactly X amount of time.
I can easily get the current time using element.currentTime, but I have no clue how to say: when element.currentTime == 5.2, runFunction() - If you know what I mean. Is there some kind of way this could be done? My current test code:
<----AUDIO WILL START PLAYING---->
http://jsfiddle.net/jfL4mcnh/
$("<audio id='audioElement'>").appendTo("body");
$("#audioElement").attr("src", "http://mp3ornot.com/songs/1B.mp3").attr("autoplay", "autoplay");
setInterval(function() {
//for some reason, $("#audioElement").currentTime won't work, so we're going old fashion
time = document.getElementById("audioElement").currentTime;
console.log(time);
}, 1000);
Also, I forgot to say this, I cannot do a setTimeout() and hit at the exact moment I want in milliseconds, because the audio can take some extra time to load, while the actual code runs exactly when it has been "seen", if you know what I mean. So no countdown. I need to be exact here.
If you need greater resolution than ontimeupdate provides, you can use a setInterval instead.
Live Demo (sound and alert box only!):
$("<audio id='audioElement'>").appendTo("body");
$("#audioElement").attr("src", "http://mp3ornot.com/songs/1B.mp3").attr("autoplay", "autoplay");
var triggered = false;
var ael = document.getElementById("audioElement");
var interval = setInterval(function(){
console.log(ael.currentTime);
if (!triggered && ael.currentTime >= 5.2) {
triggered = true;
alert("5.2 seconds reached");
}
if (ael.ended) clearInterval(interval);
}, 50);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
JSFiddle Version: http://jsfiddle.net/jfL4mcnh/15/
Well, I have done it myself.. It seems.
http://jsfiddle.net/jfL4mcnh/13/
$("#audioElement").bind("timeupdate", function() {
var currentTime = parseInt(this.currentTime, 10);
if(currentTime == 2) {
console.log("2 seconds in");
$(this).unbind("timeupdate");
}
});
You can bind timeupdate to it, then unbind it (apparently it runs the code 4 times, so I have to unbind it).
EDIT: Nope, it doesn't update fast enough to make it perfect on point. It increments each ~300ms it seems.
See this jsfiddle here
I've added the following line to the JavaScript setInterval() function:
if (time > 5.2) {
myFunction();
}
myFunction() does a console.log, which you'll see in the console.
The reason I used > rather than === is that the time reported is never precise due to fluctuations in processing. A Boolean in the condition would solve this problem:
triggered = false;
if (time > 5.2 && !triggered) {
triggered = true;
myFunction();
}

How do I regularly check the state of a page without refreshing?

I'm pretty new to (javascript) programming and I'm trying to get something automated.
There is a page that contains a countdown timer, and I want my greasemonkey script to automatically do some actions if the condition is met.
I've got this right now:
var timer = document.getElementById('timer_4975');
if (timer.innerHTML < "00:00:20"){
//Some actions
}
But this only checks the condition once when the script is loaded, when the timer goes under 00:00:20, it doesn't detect the condition is met and doesn't go to action.
Can someone guide me in the right direction?
Thanx in advance!
You can use the setTimeout or setInterval functions to perform this task.
setInterval will perform a task regularly, which is probably more suited to what you want to achieve.
Something like:
var timer = document.getElementById('timer_4975');
var intervalHandle = setInterval(function() {
if (timer.innerHTML < "00:00:20"){
//Some actions
clearInterval(intervalHandle);
}
},1000);
would check every second (1000ms). Change the 1000 value to increase or decrease the frequency of checking... once a second is likely to be often enough.
You will have to use setInterval() to execute your code more than once:
setInterval(function() {
if(timer.innerHTML < "00:00:20") {
//Some actions
}
}, 5000); //Execute this function each 5 seconds.

Restarting a setInterval() in Javascript/jQuery (without clearInterval)

I'm working on ui tabs built using jQuery. Everything works except for one issue - I did a setInterval that runs a function that does a trigger("click") so that it goes to the next tab after 5000 miliseconds. It runs through each tab fine, the issue is that if the user manually clicks on a tab, the timer for the setInterval does not restart back at 0. For example if a user were to start on tab1 at 0 miliseconds and clicks on tab2 at 2000 miliseconds, the setInterval doesn't go back to 0, it would start at 2000 and run to 5000 miliseconds and would subsequently goto tab3. I understand why it's happening, I just wonder if there were a way to restart the setInterval timing without having to do a clearInterval() and creating an entirely new setInterval(). Any insight would be appreciated.
Update
Thanks for the replies - The reason I was trying to avoid using clearInterval was because I was having issues of how to write the code in a way where the clearInterval would stop the setInterval completely. The code is setup to track whenever a user has clicked a tab. The problem is the auto change function utilizes trigger('click'), so it runs the clearInterval function I wrote also when the tabs auto-change. It seems to run fairly fine on its own, but once the user starts clicking on tabs, the setInterval behaves unusually and switches tabs unpredictably. I suspect what is happening is that several setIntervals are running at once... Here's the code (If you haven't guessed it already, I'm pretty new at javascript/jquery). I've commented out parts so that it's functional, but it still doesn't function as I intended (from first post).
// auto change tabs
if( options.interval ) {
function timerCom() {
if( !$(".controller").hasClass('paused') ) {
var i = $(".tab-current > a").attr("rel");
//alert(i);
if( i == 3 ) {i = 0};
$container
.find('a')
.eq(i)
.trigger('click');
}
}
//$("#promo-items > li > a").click(function () {
//var timer;
//if( timer != null ) {clearInterval(timer);}
timer = setInterval(timerCom, options.interval);
//});
}
No, there is no way to restart a timer set by setInterval without clearing the timer.
You can't really alter intervals or timeouts, only clear them. That said it should be a simple thing to create a function that clears the interval, and then starts a new but identical one immediately with a fresh time value.
var intervalID;
var resetTimer = function() {
if (intervalID) { clearInterval(intervalID) };
intervalID = setInterval(function() {
console.log('doing stuff!');
}, 5000);
};
timer = setInterval(function() {
timerCom();
}, options.interval);
I know this post is well over 2 years old, but I ran into a similar problem just now, and I found a solution.
I was writing an image scroller that would automatically shift to the next image after a set amount of time, and whenever I clicked the navigation buttons, the transitions moved double-time.
Here's my solution:
Make the interval variable (timer in your case) somewhat global.
i.e. in the options section (assuming it was defined earlier, and then later assigned), add a null timer variable.
var options = {
'interval',
//Other variables
'timer',
};
Then, call clearInterval twice when you handle the click event.
$("#promo-items > li > a").click(function () {
if( options.timer != null ) {
clearInterval(options.timer);
clearInterval(options.timer);
}
options.timer = setInterval(timerCom, options.interval);
});
Worked like a charm for me.
Again, sorry if this is wayyyy too late.

Categories