I've looked all over the net for a solution to the following problem: how do I create a timer that works in an inactive tab on any modern web browser?
Solutions appear to exist using JavaScript (using setInterval / setTimeout and using a Date object / timestamp), but these require the user to refocus the window to reload the timer. What if the timer finishes and the window is out of focus? I need the timer to make a noise or alert the user in some way, so these solutions do not apply.
I'm asking for a solution using any server-side or client-side language.
setInterval and setTimeout should work even if tab is not in focus (as any other actions).
Try to write this in console of new tab and switch to another tab:
setTimeout(function(){alert('hello')}, 5000)
After 5 seconds some kind of mark would appear on tab.
This is how it looks in firefox:
Related
Is it possible to run a timer in the background (in both iOS and Android) or will it be out of the app-guidelines (specifially on iOS). Right now I am having a meditation-timer-app and one of the most important things is that the time should keep on running while in background mode (if the phone display is black or the home screen is opened).
I am using an interval setInterval() - Method of 1000s to count down each second.
https://capacitorjs.com/docs/v2/apis/background-task#background-tasks says it may not be possible:
NOTE: On iOS setTimeout and setInterval won’t work once your app is in background, so don’t use them inside beforeExit.
So another idea that I would have would be to make a calendar event (for example for a Date that is 10 min in the future if you set the timer to 10mins).
Than it would be a scheduled timer event. If you reopen the app, the timer gets adapted to the calendar event.
Is this possible to wait for a specific date to happen? And how?
Do you have a better solution or can I just use the interval in the background somehow?
For my app this would be very important, since when meditating, you don't want to have the phone open. You want to start the timer and put the phone away.
Using JavaScript (and/or jQuery), Is it possible to pause the user from exiting a page for a set amount of time without showing an alert/confirmation?
(Say the user clicks on a different page or closes the window, a timer should start for three seconds [during which time something happens] and then the next page is loaded or the window closes.)
No, it is impossible in modern browsers.
(Moreover, think of how annoying that would be if every popup did that)
The closest you can do is show the dialog using onbeforeunload but you have asked to avoid this.
But why would you want to do that?
Worth mentioning, that this is a magical time. You might want to report something to the server but you suddenly can't because the user is leaving. This is one of those times things that are usually considered bad practice like synchronous ajax might make sense.
No. This is not possible. At best you can implement an onbeforeunload handler but your options at this point are very limited (you can certainly not 'wait 3 seconds').
Browsers will try to protect the user so this is behavior that browsers enforce and they have incentive to enforce it.
This works in chrome and firefox:
window.onbeforeunload = function() {
var now = new Date();
while( new Date() - now < 3000 );
};
It will also drain battery, so you are killing 2 birds with one stone.
Is it possible to create a custom modal message which 'blocks' the execution of the script until a user input?
For example, how can you achieve this without using the native window alert / prompt functions?
setInterval(function(){
alert('Click OK to Continue'); // timing stops until user hits ok
},4000);
I know you could have your custom dialog invoke a callback function on user input, but I'm interested in being able to force this blocking behaviour
Is it possible to create a custom modal message which 'blocks' the execution of the script until a user input?
No. There is no way to block either execution or user interaction as effectively as a native popup (since with custom popups the user is always technically capable of using developer tools to get out of it).
However, as pst says in the comments on the question, asynchronous lightboxes are not onerous, and are almost as effective at blocking user interaction as popups, so I recommend finding a library that provides lightboxes you like and running with that.
For example, how can you achieve this without using the native window alert / prompt functions?
You can't use that code to do what you say it will even with native window alert / prompt functions (see this fiddle - wait 4 seconds before closing popup). You'd need the following:
function timeoutFunction() {
alert('Click OK to Continue'); // timing ACTUALLY stops until user hits ok
setTimeout(timeoutFunction, 4000);
}
setTimeout(timeoutFunction,4000);
Which is something that you can't implement (precisely - see above on lightboxes) without native popups.
Even while(true) loops won't generally block as well as a popup - firefox at least has a "stop script" message that pops up after it's been going too long, and I'm fairly sure other major browsers do too.
No, you can't (at least not in a browser). Javascript APIs are mostly async. alert/prompt are exceptions. However, it's not very hard to work with async prompts and callbacks.
A bit old, but in case it helps, I've found my solution with this:
var answer = confirm("are you sure?");
if(!answer)return;
I have this functionality built in Jquery/ javascript where a user is notified when their session is about to be timed out. Then they are given an option to extend it. If they don't make a choice the pop up closes itself and the browser is redirected to the login page. It worked perfectly fine for a while. But now I noticed it works correctly only if I am active on the computer. If the computer is left unattended for an entire day, the pop up does not begin the countdown until the user unlocks the computer and logs in again.
Is anybody aware of this behavior where ie stops executing javascript when the computer is left unattended for a long time?
Update: Is there a way to keep the tab from sleeping? Without that, the browser won't be able to redirect at the right time.
setTimeout only works when the tab is active. In some browsers even changing tab will make it stop counting. So not only if you are on the computer but if you're not on the specific page it might not work. Also on mobile devices with multitasking it's bound to fail, forget about tabs, applications often go to suspended mode.
Take a look at this question, it offers the same solution as Luka with a code example:
How can I make setInterval also work when a tab is inactive in Chrome?
You might want to do two checks on the time passed, one to check if you need to show the popup, and one to close the popup, using the total time passed instead of having a different count down.
i would suggest logging the current time when the page is loaded and then calling a function every 10 seconds of so that checks if the time passed is more than x amount, the reason your problem occurs is most likely because the default timeout function only counts down while the page is being rendered.
Alright, I've found a bunch of answers concerning native functions like window.onblur and window.onfocus... But they won't help so I'd like to be more specific
Say you open several tabs of one website
Say you receive a message and there's a sound to announce the message
As you have several tabs opened, you will hear the sound the number of opened tabs. Which makes a how'd'u'callit symphony
Best solutions I've found so far, but which don't work
1. window.onfocus and window.onblur
2. Play sound if var infocus evaluates to true, don't play if not
3. It is crossbrowser
4. It is simple
5. It does not work
Why the best solution won't work? Say you switch focus to another tab of a different website, your website loses focus so you won't hear the sound. Even worse, say you switch to another program, then the browser itsel loses focus and you won't hear the sound
So what shall I do?
You could save the timestamp of the last onFocus() event in a JavaScript variable and in a cookie (access set to your website root). Then when you want to play the alert sound, you compare the current values of the variable and the cookie and only play the sound if those two match.
Alright, two weeks after it seems like I've found the real solution. Which actually proves that if you want to do something, don't ask for help, just do it
This is what I did:
Create a cookie with a randon id and the current time (winid + t1). The cookie is created by each opened tab on loading.
document.cookie = 'winid='+winid+t1;
Create a function which will update the current time in the set cookie, say, every 3 seconds (I kindda don't like to overflow clients, so it's 3 secs not 1). If the function finds out that the winid in the cookie and the winid of the current tab don't match and 3 secs have elapsed, then the tab was closed, redefine the primary tab inside the same function.
window.setInterval(setwinid,3000);
This is it, every time you need to, say, play a sound, you should check first, whether it is the tab which is to play it
The trick is that each tab has its own winid. But only one winid is stored in cookie, is updated and thus allows the one tab to perform actions. Pretty simple. I actually started using this method for updating messages in the box across all tabs not only for playing music
One solution would be to have a server-side solution that would play the notification only once. You don't specify how the site receives the messages, but I assume it's some form of AJAX call that gets the message from the server and the messages are saved in a database.
Add a flag to the database that signifies that the message has been sent. Set the flag the first time the user's browser queries for new messages. On the page itself play the sound only if the flag has not been set, otherwise don't play the sound. Now only the first page that fetches the message will play the sound.