I am creating a MCQs quiz and there is a time for each question. I have also used onbeforeunload in my script to prevent the user from accidentally navigating away from the quiz page. But when that alert gets display my setInterval counter stop working. How can i make the countdown to not stop even if there is an alert?
To further explain my problem here is the FIDDLE
Browser dialogs are blocking. All script execution stops when they are open. You cannot change this behaviour.
Instead of starting with 90 seconds and trying to reduce that by 1 second every second, calculate the current date + the 90 seconds to get the end date. Then on each call of your setTimeout, calculate the current number of seconds until the end date.
The timer won't advance while the alert is visible, but it will skip to where it should be when the alert is dismissed.
A possible workaround could be that you declare a var timeCount = new Date() to store the time if a beforeunload() is called and use that to calculate passed time/missed seconds. But otherwise what Diodeus said is correct.
Related
I have a page that presents a test, where javascript sets a timeOut to abandon the page if the user waits too much (180") before giving an answer and pressing submit.
It has to be done for various reasons, and I cannot modify the committment.
After 180" on the page, so, currently the code goes back to a beginningpage.php where the user will have to re-enter its unique ID to continue the test.
This is the simple javascript code:
setTimeout(function () {
window.location.href= "beginningpage.php";
}, 180000);
Everything runs smooth. Now I need to modify the code to better manage the case. We assume that if the user has gone away, it will not be able to answer to an alert box. So let's say we push a confirm() after those 180".
How to write code so that - when the confirm() windows is displayed - if nobody clicks a confirm button (for let's say 30") the code automatically close the confirm window and leaves the page going back to beginningpage.php?
Otherwise, if the user is still at his desk and is simply wondering about the answer to give, he must be given the possibility to click "ok, I hurry up" to remain on the page for say another 60". That means that after the first displaying of the confirm window, the timeout must be set to a different deadline, not 180000 as before but 60000.
Maybe the idea of using different window.locations.href is not the right one.
How could be the code to accomplish everything I need as above explained?
Just don't use a confirm box... Show a div with two buttons after 180 seconds and then start counting your 30 seconds.
So let's say we push a confirm() after those 180".
How to write code so that - when the confirm() windows is displayed - if nobody clicks a confirm button (for let's say 30") the code automatically close the confirm window and leaves the page going back to beginningpage.php?
You can't. confirm, alert, and promopt are 1990s holdovers with stop-the-world behavior. (Mostly. Browsers are eroding that slowly over time.) That means none of your JavaScript code can run while the archaic window is showing.
Instead, switch to using modern alerting techniques (showing a "modal" div, etc.) so that your JavaScript code can use setTimeout to give up after the relevant amount of time.
You can never achieve this with alert or confirm because they block further js execution till the popup is active.
You need a custom modal with html element and a js function
All you have to do is call clearTimer for auto-page reload based on the response from custom confirm modal.
var x = document.getElementById("stopReloadBtn")
var reloadTimer
setTimeout(function() {
x.style.display = "block"
reloadTimer = setTimeout(function() {
window.location.href = "beginningpage.php"
}, 5000)
}, 5000);
function stopReload(){
clearTimeout(reloadTimer)
x.style.display = "none"
}
<button id="stopReloadBtn" style="display: none" onclick="stopReload()">Still Here?</button>
I have reduced the timers to 5 sec in this code. A button will appear after 5 sec. After which you will have 5 sec to click this button else the page will reload.
I'm creating an audio web player which I would like to function continuously, meaning that when a piece of audio finishes playing, it moves onto playing the next one.
However, I have come across a problem where everything works as it should, but once the previous audio finishes playing, and the next one starts, every 2 seconds, the new one will play & pause; continuously.
This is my current JavaScript code block:
function playPauseButton(button, wave, trackID){
var button = $(button); // play button
if(wave.isPlaying()){ // if the audio is playing and the user clicks play button, pause the audio
button.removeClass("playing");
wave.pause();
} else { // vice versa
button.addClass("playing");
wave.play();
}
waveDuration = wave.getDuration(); // audio duration
var nextTrack = ++trackID; // get the current audio track ID and plus 1 to get the new track ID
setInterval(function(){ // check every 2 seconds if the audio is finished playing
if(wave.getCurrentTime() >= waveDuration){ // if it has, make the play button a pause button
button.removeClass("playing");
$(nextTrack + '-ppbutton').click(); // simulate new track play button click
}
}, 2000);
}
& my very simple HTML play button:
<!-- onclick play audio (if paused), pause audio (if playing) !-->
<div onclick="playPauseButton(this, a2wave, 2);" id="2-ppbutton"></div>
<!-- 2 is the id !-->
I've been trying to figure this out for hours, however, it is still confusing me (I'm not that good at JavaScript)
All help & suggestions are appreciated.
I've tried to comment on everything to help you understand
UPDATE:
Thanks to Vlaz for fixing my issue; really appreciate it! :)
However, if people would still like to make suggestions or edits, you are more than welcome too!
Thanks.
Problem
Your usage of setInterval will launch a new ticker every time the button is pressed. So after three presses, you'd have three of them running. Also, remember that each will be running their own checks, as well. So I believe I know where your problem is, here is an overview
setInterval is called the first time, let's call it intervalPrime. Let's assume the duration of the song is 60 seconds.
The song continues with a check every 2 seconds, eventually ends.
A new setInterval is called when the play button is clicked - this creates a new interval - let's call it intervalSecond. This one will be checking for a new song and new duration, however the details are irrelevant.
The song plays and intervalSecond monitors if it's finished yet.
At the same time intervalPrime is still doing it's check. And since wave.getCurrentTime() likely returns 60 (end of the song), then the check it does is 60 >= 60 which passes, so it clicks the button.
How to avoid it
Remove old intervals
What you could do is ensure you only have one setInterval active at a time. The function returns an ID of the timer, so you could do something akin to this
var currentChecker;
function playPause() {
/* .... */
if (shouldClick) {
clearTimeout(currentChecker);
currentChecker = setInterval( /* ... */ );
}
}
(illustrative)
So, essentially try to maintain a single one by stopping the previous interval before starting a new one.
Keep only one interval
An alternative is to only have one interval active and maintain a state, so you can have something like
var masterLoop = setInterval(function() {
var wave = getCurrentWave(); //fetching it will depend on your application
if(wave.getCurrentTime() >= wave.getDuration()){
/* handle what happens */
}
} , 2000);
Use setInterval when the song finishes.
I'm not familiar with the API you use for playing the sounds, but if it's possible to hook onto the end event, you might be able to use simple setTimeout when that occurs, like so
//assuming the API allows to do something like this
wave.onFinish(function() {
setInterval(playNext, 2000);
})
More than one of these
If the API does not provide a way to hook onto the finished playing event, a better alternative is to combine the last two. Have a master loop that checks the state of the track and when finished, uses setInterval to schedule the next song. The interval delay will probably need to be set lower, but it will lead to a more consistent time between tracks, since a song might end and 0.3 seconds later the interval does it's check and plays the song, or a song might end right after the interval finished, so you'd have a gap of 2 seconds.
Maintain a single setTimeout
It's similar to the first suggestion of clearing old intervals but not exactly the same.
The thing is that you don't need to keep checking if the song has finished playing, because you already know when it will finish. So, when it's played, you can use setTimeout to queue up the next song
//assuming wave returns time in milliseconds
var playNextIn = (wave.getDuration() - wave.getCurrentTime()) + 2000;
nextSongTimer = setTimeout(function() {
/* code to play next song */
}, playNextIn);
So, this way you don't need to keep checking.
However, the only problem would be if a user clicks pause in which case you will need to call clearInterval(nextSongTimer) as it's no longer needed. So this way, you only need to kick off a timer once every time a song is played.
Every time you click the play/pause button, you call setInterval. So you're likely to have several time-based triggers at the same time and the condition probably keeps being true.
What if you replace your call to setInterval with:
var trigger = setInterval(function(){ // check every 2 seconds if the audio is finished playing
if(wave.getCurrentTime() >= waveDuration){ // if it has make the play button, a pause button
button.removeClass("playing");
$(nextTrack + '-ppbutton').click(); // simulate new track play button click
clearInterval(trigger);
}
}, 2000);
I'm new to JavaScript.
I'm writing a simple code to add it in a chrome extension call it Shortkeys.
I just want the code to make a simple action:
Wait for a click of the mouse and then click a button in certain positions of the screen after 500 ms...
This is what I have written until this moment but is not working:
document.addEventListener('click', TimerThenPlay);
function TimerThenPlay(e) {
setTimeout(500)
document.elementFromPoint(1175, 85).click();
stop(TimerThenPlay);
clearTimeout(TimerThenPlay);
return;
};
What I'm doing wrong?
EDIT:
I have an APP running on Chrome...
I need to Click a Link and wait 500 ms to click a button... i can do that manually but sometimes dsnt work and i have to try again..
I realize that chrome has an extension that you can inject to the page a javascript code when u press a key in your keyboard. Thats why im using Shorkeys (if u know a better extension for this, just tell me).
Well... i have assign the < key to run the code...
What i need, is that everytime that i hit the < key... Chrome waits for a click (so i have time to look for the link that i want to open with de button)...
And when i click the link, it waits 500 ms and then click the button in the position that i select ( i cant use the Button ID cause it changes every minute).
I have tried the codes above and it works for the first time.. then, i dnt know why is keeping clicking 500 ms after a make a mouse click in the next pages... How can i stop that loop in the next page?
function TimerThenPlay(e) {
setTimeout(function(){
document.elementFromPoint(1175, 85).click();
stop(TimerThenPlay);
clearTimeout(TimerThenPlay);
},500)
}
SetTimeout method takes two arguments. First is function to execute after second argument time passes.
Hope this helps
Your setTimeout syntax is wrong.
Syntax of setTimeout:
setTimeout(function(){}, time)
you need to update your setTimeout function
function TimerThenPlay(e) {
setTimeout(function(){
document.elementFromPoint(1175, 85).click();
stop(TimerThenPlay);
clearTimeout(TimerThenPlay);
return;
},500)
};
At the moment I am using ajax requests every 10 minutes to update certain content and other time intervals for others.
I do this using jQuery by:
On mouse move, the active page is checked
If the active page has not be updated within the given time interval, the page is updated
I'm doing this because although i want the content to stay up to date, I don't want it to be sending requests in the background (when the user is not using the application). Doing this also means that if the user has not used it for more than the time period, when they start to use it again it will automatically update.
I'm wondering just how efficient this is as whenever the mouse moves the checks are called (and has slowed down performance a bit - especially when trying to click links) - is the a more efficient way to do this?
Thanks!
I would rather activate/reset a timer, on say, 60 seconds, on movement of the mouse, and set your fixed-interval checks to only run if that timer is above zero.
That way, checks aren't made every time the mouse moves, and if the user becomes inactive, update checks stop after 60 seconds.
Another possible solution would be to use the window blur and focus events to determine if the window is active:
var checkForContentUpdates = true;
$(window).focus(function() {
checkForContentUpdates = true;
});
$(window).blur(function() {
checkForContentUpdates = false;
});
Your AJAX routine would then key off of the checkForContentUpdates bool.
I'm sure that there are scenarios where this isn't fool-proof, so you'd likely have to combine this method with other logic.
I am having a Javascript function which displays timer.
Now,when timer reaches 2 minutes, I want to display a alert and continue my timer function.
But,my timer function stops till user clicks 'Ok' and then resumes from 1:59 secs.
Can anyone tell me how to keep the timer function running while popup box is displayed?
Here's my function to display timer.
var minutes=5;
var seconds=59;
function time_display(){
if(minutes==2 && seconds==0){
setTimeout('display_time_alert_two_minutes_left()',100);
}
if (seconds<=0){
seconds=59;
if(minutes>0)
minutes-=1;
}
else
seconds-=1;
$('time_left_in_minutes').innerHTML = minutes+"."+ ljust_zero(seconds);
setTimeout("time_display()",1000);
}
time_display();
and this is my alert function.
function display_time_alert_two_minutes_left(){
alert('Two minutes left');
}
Alert is a blocker, use custom javascript popups like lightbox,lytebox,jquery dialog,fancybox etc.
Or you can simply show/hide a floating div. This will solve the problem of your timer
getting stuck, and also enhance your user experience.
How about you use something thats no so intrusive, something like this
As alert() stops the rest of the javascript code executing, it would be better to use something that doesn't require an imperitive style of incrementing time.
How about you actually use the time/date functionality, which will 'keep counting'?
Edit : This will stop the web page updating when you call alert() but it will keep counting fine whilst an alert is open.