JavaScript - clearWatch() not triggering on setTimeout() - javascript

I'm encountering some issues with JavaScript's watchPosition and clearWatch functions that I don't quite understand, would appreciate it if someone could help out.
First off, the function in question...
function location(x){
var getLocation;
var lat_input = $(x).find(".latitude");
var lon_input = $(x).find(".longitude");
var acc_input = $(x).find(".accuracy");
function showPosition(position) {
latitude = position.coords.latitude;
longitude = position.coords.longitude;
accuracy = position.coords.accuracy;
$(lat_input).val(latitude);
$(lon_input).val(longitude);
$(acc_input).val(accuracy);
setTimeout(function(){
navigator.geolocation.clearWatch(getLocation);
alert('done');
}, 10000);
};
getLocation = navigator.geolocation.watchPosition(showPosition, null, {maximumAge: 0, timeout: Infinity, enableHighAccuracy: true});
};
In particular, my problem is with the code in the setTimeout section.
When I run this function on my laptop, everything starts out ok - the .longitude, .latitude, and .accuracy fields are populated accordingly. After 10 seconds, setTimeout is triggered - I can't say if clearWatch runs successfully (since the computer is pretty limited in its ability to find itself), but the odd behavior that I note here is that alert('done') is triggered twice.
When I run this function on my phone (the intended platform), everything gets off to a similarly good start, but after 10 seconds, alert('done') starts triggering endlessly, sometimes in immediate succession, sometimes with a few seconds in between. Most distressing, however, is that clearWatch doesn't appear to run at all - that lat, long, and accuracy fields continuously update after the 10 second mark.
If anyone can see what I am doing wrong here, your guidance would be much appreciated.

I hit a similar issue. I found the following code did not stop the watch:
navigator.geolocation.clearWatch(locationID);
STEP 1: Create a variable and assign it to navigator.geolocation
var geoLoc = navigator.geolocation;
var geoWatchID = geoLoc.watchPosition(
onGPSSuccess, onGPSError,
{ maximumAge: 300, timeout: 1500, enableHighAccuracy: true });
STEP 2: Stop Watch use the var geoloc not navigator.geolocation.clearWatch()
geoLoc.clearWatch(geoWatchID);
geoWatchID = null;
See http://www.tutorialspoint.com/html5/geolocation_clearwatch.htm

Without knowing the libraries to re-create the code, I can't duplicate the issue so I can only give something to try.
Add a timer variable to your outer scope.
clearTimeout(timer);
timer = setTimeout(function(){
navigator.geolocation.clearWatch(getLocation);
alert('done');
}, 10000);

Related

PIXI.extras.MovieClip catch end of loop

I am using PIXI.extras.MovieClip to play a short animation (about 60 frames) and due to not knowing how many FPS there will be on users device I can't tell how much time exactly does it take to play all the frames. setTimeout also does not guarantee that function will be triggered exactly after specified time so it's kinda not my way of solving this too.
When the playing of animation is finished I want to trigger some events in code to remove the MovieClip and write some logs.
The problem is that I can't find any kind of trigger/callback that will be called when last frame of animation was rendered.
example code:
movie = new PIXI.extras.MovieClip(someFrames);
movie.animationSpeed = 1;
movie.onComplete = animationFinished;
movie.play()
animationFinished = function () {
console.log("Animation just reached it's end.");
movie.gotoAndStop(0);
};
the obvious problem is, that movie.onComplete is never called. Is there any way to make this work?
Thanks for any suggestions and ideas.
Happy coding!
movie = new PIXI.extras.MovieClip(someFrames);
movie.animationSpeed = 1;
movie.onComplete = animationFinished;
movie.loop = false;
movie.play();
animationFinished = function () {
console.log("Animation just reached it's end.");
movie.gotoAndStop(0);
};

setInterval in javascript based on changes made

I'm having an issue with a javascript requirement. I have a html calling a script perpetually every 1500ms using setInterval.
var t = setInterval(loadData(),1500);
The loadData function calls a script which returns a JSON as a list, what I want to do is to change from a fixed interval to a variable interval. For instance, if there are no changes made between two calls to the script, I must set another value for the interval. I heard I could use jquery linq to compare the length of the list at the beginning and the list when refreshing to change the time value. I also heard I could save the value of count in a cookie to compare always.
Any idea please? I would be grateful. Thanks in advance.
I'm guessing you're trying to do:
var speed = 1500,
t = setInterval(loadData, speed);
function loadData() {
if (something == true) {
something = false;
speed = 3000;
clearInterval(t);
t = setInterval(loadData, speed);
}else{
//do something
}
}
You should just reference the function, adding the parenthesis runs the function immediately. When using a variable for the speed, you'll need to clear and run the interval function again to change the speed.
if the interval is variable, then you can't use setInterval, which period won't be changed after the first call. You can use setTimeout to alter the period:
var period=1500
var timer;
var callback = function() {
loadData();
timer = setTimeout( callback, period )
};
var changePeriod = function( newPeriod ) {
period = newPeriod;
}
//first call
callback();
now, you just need to call changePeriod( ms ) to change the period afterwards

javascript timed event

I''m getting input as a stream of x/y coords, and I'd like to trigger an event if those coords fall within a specified range for a given period of time (say 2 seconds). Could someone suggest a way to do this?
Algorithmically, when you first detect that it's in the range, you do a setTimeout() for 2 seconds. From then on, if the coords stay in the bounds and the timer is already set, you do nothing. If the coords fall outside the bounds, you stop the timer with clearTimeout(). If the timer fires before you've cleared it, then the coords have stayed in the bounds for the desired time.
Here's a code example:
var myTimer = null;
function processCoordinatePair(x,y) {
if (inBounds(x,y)) {
if (!myTimer) {
setTimeout(function() {
// we stayed in bounds for 2 seconds, do whatever needs doing
myTimer = null; // clear timer for future use
}, 2000);
}
} else { // not in bounds any more
if (myTimer) {
clearTimeout(mytimer); // if timer was running, stop it
myTimer = null;
}
}
}
The implementation of the inBounds() function is obviously up to you since you haven't described that part of the problem.

When using setInterval, if I switch tabs in Chrome and go back, the slider goes crazy catching up

I have a jQuery slider on my site and the code going to the next slide is in a function called nextImage. I used setInterval to run my function on a timer, and it does exactly what I want: it runs my slides on a timer. BUT, if I go to the site in Chrome, switch to another tab and return, the slider runs through the slides continuously until it 'catches up'. Does anyone know of a way to fix this. The following is my code.
setInterval(function() {
nextImage();
}, 8000);
How to detect when a tab is focused or not in Chrome with Javascript?
window.addEventListener('focus', function() {
document.title = 'focused';
},false);
window.addEventListener('blur', function() {
document.title = 'not focused';
},false);
To apply to your situation:
var autopager;
function startAutopager() {
autopager = window.setInterval(nextImage, 8000);
}
function stopAutopager() {
window.clearInterval(autopager);
}
window.addEventListener('focus', startAutopager);
window.addEventListener('blur', stopAutopager);
Note that in the latest version of Chromium, there is either a bug or a 'feature' which is making this less reliable, requiring that the user has clicked at least once anywhere in the window. See linked question above for details.
I post an answer here: How can I make setInterval also work when a tab is inactive in Chrome?
Just do this:
setInterval(function() {
$("#your-image-container").stop(true,true);
nextImage();
}, 1000);
inactive browser tabs buffer some of the setInterval or setTimeout functions.
stop(true,true) - will stop all buffered events and execute immadietly only last animation.
The window.setTimeout() method now clamps to send no more than one timeout per second in inactive tabs. In addition, it now clamps nested timeouts to the smallest value allowed by the HTML5 specification: 4 ms (instead of the 10 ms it used to clamp to).
A few ideas comes to mind:
Idea #1
You can make it so that a short burst is idempotent. For example, you could say:
function now() {
return (new Date()).getTime();
}
var autopagerInterval = 8000;
function startAutopager() {
var startImage = getCurrentImageNumber();
var startTime = now();
var autopager = setInterval(
function() {
var timeSinceStart = now() - startTime();
var targetImage = getCurrentImageNumber + Math.ceil(timeSinceStart/autopagerInterval);
if (getCurrentImageNumber() != targetImage)
setImageNumber(targetImage); // trigger animation, etc.
},
autopagerInterval
);
return autopager;
}
This way even if the function runs 1000 times, it will still run in only a few milliseconds and animate only once.
note: If the user leaves the page and comes back, it will have scrolled. This is probably not what the original poster wants, but I leave this solution up since it is sometimes what you want.
Idea #2
Another way to add idempotence (while still keeping your nextImage() function and not having it scroll to the bottom of the page) would be to have the function set a mutex lock which disappears after a second (cleared by another timeout). Thus even if the setInterval function was called 1000 times, only the first instance would run and the others would do nothing.
var locked = false;
var autopager = window.setInterval(function(){
if (!locked) {
locked = true;
window.setTimeout(function(){
locked=false;
}, 1000);
nextImage();
}
}, 8000);
edit: this may not work, see below
Idea #3
I tried the following test:
function f() {
console.log((new Date()) + window.focus());
window.setTimeout(f, 1000);
}
f();
It seems to indicate that the function is being called every second. This is odd... but I think this means that the callbacks are being called, but that the page renderer refuses to update the page in any graphical way while the tab is unfocused, delaying all operations until the user returns, but operations keep piling up.
Also the window.focus() function doesn't say if the window has focus; it GIVES focus to the window, and is thus irrelevant.
What we want is probably this: How to detect when a tab is focused or not in Chrome with Javascript? -- you can unset your interval when the window loses focus (blur), and reset it when it gains focus.
I don't know exactly what is going on in your function nextImage(), but I had a similar issue. I was using animate() with setInterval() on a jQuery image slider that I created, and I was experiencing the same thing as you when I switched to a different tab and back again. In my case the animate() function was being queued, so once the window regained focus the slider would go crazy. To fix this I just stopped the animate() function from queuing.
There are a couple ways you can do this. the easiest is with .stop(), but this issue and ways to fix it are documented in the jQuery docs. Check this page near the bottom under the heading additional notes: http://api.jquery.com/animate/
I had faced similar issue, somehow this code below works fine for me.
var t1= window.setInterval('autoScroll()', 8000);
window.addEventListener('focus', function() {
focused = true;
window.clearInterval(t1);
t1 = window.setInterval('autoScroll()', 8000);
},false);
window.addEventListener('blur', function() {
focused = false;
window.clearInterval(t1);
},false)
function autoScroll()
{
if ( running == true){
if ( focused = true){
forwardSlide();
}
}
else {
running = true;
}
}
If you are using Soh Tanaka's image slider then just add this...to solve your Google Chrome issue:
$(".image_reel").stop(true, true).fadeOut(300).animate({ left: -image_reelPosition}, 500 ).fadeIn(300);
Take note of the .stop() function. Ignore the fading in and out stuff, that's what I used on my version
Thanks
Seconding the comment by jgerstle to use page visibility events instead, see https://www.w3.org/TR/page-visibility/#example-1-visibility-aware-video-playback for more around subscribing to 'visibilitychange' for hidden/visible states.
This seems to be more useful than focus/blur these days as it covers visible-but-not-selected windows if concerned also about multi-window operating systems.

Timeout a function in JavaScript/jQuery

I've got the following problem:
I'm using Google Maps on my site. I've attached the following eventListener to the map itself:
google.maps.event.addListener(map, 'bounds_changed', scheduleDelayedCallback);
The event bounds_changed is called every time someone drags the map. My Problem is, that it is called several times during the drag process. Now I need to find a way to call the callback function only, if it wasn't called during the last, let's say, 750 milliseconds.
I did this using these two functions:
function fireIfLastEvent() {
var now = new Date().getTime();
if (lastEvent.getTime() + 750 <= now) {
this_function_needs_to_be_delayed();
} else {
$("#main").html('Lade...');
}
}
function scheduleDelayedCallback() {
lastEvent = new Date();
setTimeout(fireIfLastEvent, 750);
}
This method works great in Chrome and Opera. In IE it works sometimes, in Firefox it never works (it calls the functions even if the 750 milliseconds haven passed).
Is there any rock-solid way to timeout a function call?
Thanks.
You shouldn't need a timeout here.
function scheduleDelayedCallback() {
var now = new Date();
if (now.getTime() - lastEvent.getTime() >= 750) {
// minimum time has passed, go ahead and update or whatever
$("#main").html('Lade...');
// reset your reference time
lastEvent = now;
}
else {
this_function_needs_to_be_delayed(); // don't know what this is.
}
}
Your explanation of what you want to happen isn't the clearest so let me know if the flow is wrong.

Categories

Resources