I have an issue where I set an interval on a button press and try to clear it when the button is pressed again. I also have it set up so that the interval is set when user leaves the page and when he comes back, the interval should get cleared.(I am using a pause plugin, so .pause() and .resume() are a thing). This is the javascript code:
var check
var pauseactive
function pause() {
$('.box').pause();
$('#pauseimg').attr('src','buttonimg.png');
$('#pause').attr('ID','resume');
check=setInterval(pausecheck,10);
pauseactive=1;
}
function resume() {
$('.box').resume();
$('#pauseimg').attr('src','pause.png');
$('#resume').attr('ID','pause');
window.clearInterval(check);
pauseactive=0;
}
$(document).on('click','#pause',pause);
$(document).on('click','#resume',resume);
$(window).blur(pause); //this is also surrounded by $(document).ready()
$(window).focus(resume); //this is also surrounded by $(document).ready()
EDIT (better explanation):
When I click the #pause button, it does what it's supposed to do. When I then click the #resume button, it clears the interval correctly.
When I leave the page, the pause function activates correctly and when I come back, the resume function acts as it should and clears the interval.
The problem comes when I click the #pause button and then leave the page. After that when I come back, the function doesn't clear. Could that be because it's doing the setInterval twice?
Are you confusing between pause and resume? Coz the code of clearInterval and setInterval needs to be swapped:
function pause() {
$('.box').pause(); // Give the (); here.
$('#pauseimg').attr('src','buttonimg.png');
$('#pause').attr('ID','resume');
window.clearInterval(check);
pauseactive=1;
}
function resume() {
$('.box').resume();
$('#pauseimg').attr('src','pause.png');
$('#resume').attr('ID','pause');
check=setInterval(pausecheck,10);
pauseactive=0;
}
You forgot to call the function. Instead it just refers to the pause function. That has been corrected.
So once the pause() is invoked, the interval should be cleared. That has been swapped now. Please check.
Related
I am using a simple script which :
displays a message after 3 seconds if user has not clicked by then (using a setTimeout),
then if user clicks within 5 seconds, then the message should not appear within the defined setTimeout,
after this previous click if the user does not click for 5 seconds, then the user will see the message and so on...
this goes on a like a loop.
My script acually works but I have an issue because it seems it is double firing "exponentially". I think my error is how I created this "loop" and self referencing the setTimerForMsg inside itself.
Here is a Demo: https://jsfiddle.net/3wm7z576/11/
Here is the code:
html
<div id="zone">
<span id="msg" class="displayNone">this is the messager</span>
</div>
js
setTimerForMsg(3000, 5000);
function setTimerForMsg(initial_timelaps, new_timelaps) {
var timer = setTimeout(showMsg, initial_timelaps);
$("#zone").on('click', function(e) {
//if user clicks before msg appears (but after timer was initiated )
clearTimeout(timer);
//if user went beyond timer laps and msg already visible on Step (n)
//remove it when move to Step (n+1)
$('#msg').addClass('displayNone');
console.log("message1");
//loop the process for the next Step
setTimerForMsg(new_timelaps, new_timelaps);
});
}
function showMsg() {
$('#msg').removeClass('displayNone');
console.log('message2');
}
This issue is important because while this script is simple, in my real app it does other things that could drain the browser performance so I can't have them be done 64 times!
And you can see here in the console of the Demo, each time I click the events occur twice : 2 times , then 4 times then 8, then 16, then 32 times, and so on...
use $("#zone").off('click', ... to remove the eventListner you previously added. Otherwise you're just adding more and more click actions.
Documentation here
Well first of all your new_timelaps parameter is unused, this might cause some confusion.
As for the exponential growth in logs, this is caused by the fact that you don't remove your event listener, so everytime the time for your interval is passed or you click ur button another click event with the same function is aplied to your button.
How you would solve this is by using
$( "#zone").unbind( "click" )
to make sure the event is only aplied once and not get aplied again or the old ones get removed.
I am toggling the boolean variable "userTurn". There are two functions that set the value of "userTurn":
runGame(), which sets "userTurn" to true after the last sound in the current round is played.
buttonClick(), which should only be executed if "userTurn" is true. buttonClick sets "userTurn" to false after the user successfully copies the current pattern, or if the user makes a mistake.
I am evaluating the value of "userTurn" in a conditional statement that is inside of a click event.
$(".quarter").on('click', function(){
if( userTurn===true && isOn===true){
var color = $(this).attr('id');
clearTimeout(buzz);
buttonClick(color);
}
})
After the user successfully copies the current pattern, or if the user makes a mistake, "userTurn" is set to false. The problem I am running into is, after "userTurn" is set to false, the code inside the conditional statement is still executing. The goal is for ".quarter" to only be clickable when "userTurn" is true. Why is the buttonClick() function still executing when ".quarter" is clicked even when "userTurn" is false??
Here are the two functions that set the value of "userTurn":
runGame():
function runGame(){
if(isOn===true){
userTurn = false;
count();
playPattern(order, index);
if(index===counter-1&&userTurn===false){
userTurn=true;
clearInterval(play);
buzz = setTimeout(buzzer, 10000);
}else{
index++;
}
} else {
clearInterval(play);
clearTimeout(buzz);
}
}
2.buttonClick():
function buttonClick(color){
var yellowSound = document.getElementById("horseSound");
var redSound = document.getElementById("endFx");
var greenSound = document.getElementById("westernRicochet");
var blueSound = document.getElementById("robotBlip");
$("#red").mousedown(function(){
$("#red").css("background-color", "#ff4d4d");
redSound.play();
});
$("#red").mouseup(function(){
$("#red").css("background-color", "#ff0000");
redSound.pause();
});
$("#blue").mousedown(function(){
$("#blue").css("background-color", "#0000e6");
blueSound.play();
});
$("#blue").mouseup(function(){
$("#blue").css("background-color", "#000099");
blueSound.pause();
});
$("#green").mousedown(function(){
$("#green").css("background-color", "#00e600");
greenSound.play();
});
$("#green").mouseup(function(){
$("#green").css("background-color", "#009900");
greenSound.pause();
});
$("#yellow").mousedown(function(){
$("#yellow").css("background-color", "#ffff4d");
yellowSound.play();
});
$("#yellow").mouseup(function(){
$("#yellow").css("background-color", "#ffff00");
yellowSound.pause();
});
if(color===order[compareIndex]){
userPattern.push(color);
console.log(userPattern, "match");
buzz = setTimeout(buzzer, 10000);
compareIndex++;
if(userPattern.length===counter){
userTurn=false;
compareIndex=0;
index=0;
counter++;
count();
userPattern.length=0;
play = setInterval(runGame, 2000);
clearTimeout(buzz);
}
} else {
userTurn=false;
console.log('don\'t match');
clearTimeout(buzz);
index=0;
compareIndex = 0;
userPattern.length=0;
buzz = setTimeout(buzzer, 1);
}
}
TURN DOWN YOUR VOLUME BEFORE GOING TO THE CODEPEN!!
Here is a link to the codepen.
To start the game click "On Off" and then click "start". The timing is slow so you have to wait for the pattern to play, then click the buttons in the same order as they were played. The problem is seen after the first sound is played. From that point on any click the user makes will play the sound and light up the button, even when the game is playing the pattern and "userTurn" is false. Also be warned, this is still a work in progress, there are a couple of other bugs I'm working on, for example the the first turn the user makes will not light up or play the sound, but the selection is pushed into the correct array and the game will proceed properly based on your selection. I know this is a lot of info but I'm stuck on this so any feed back will be very appreciated. Thanks!
You're using buttonClick to handle clicking the buttons, but inside buttonClick you're setting mouseup and mousedown event listeners for each button as well. Since the individual buttons have their own mouseup and mousedown listeners, the events will happen whether or not buttonClick is called again.
You would have to check if userTurn is true inside of each of those event handlers as well to prevent them from triggering. Also, it would better to set these outside of buttonClick so you won't be adding new listeners every time buttonClick gets called.
The Issue
There is a timeout function below that ajaxes in the html of the page instantly after an interval of 1200 (jQuery timeout), and it is great until the user presses enter before the timeout is finished, or after, and the html for the page is called twice unnecessarily.
The Code I am using
The function called onkeyup of the input
var timeoutReference;
function instant(){
var val=some filters;
if(val!=''){
if(timeoutReference)clearTimeout(timeoutReference);timeoutReference=setTimeout(function(){
ajaxHTML();
},1200);
}
}
Same function is called on enter
$(document).on('keypress',function(e){
if(e.keyCode==13){
ajaxHTML();
}
});
Question
What can I add to stop the Timeout Function if enter is pressed before it, or how can I prevent the same HTML document from being called twice? Thanks
You've got all the code you need in what you've posted. Just clear the timer when the user presses enter, which will prevent the callback from firing.
if(e.keyCode==13){
clearTimeout(timeoutReference);
ajaxHTML();
}
At the moment, your code calls ajaxHTML() when the user presses enter, but it may already be queued up to call that from your setTimeout set by instant() - resulting, as you say, in two AJAX calls.
Suppose you want to display an alert 3 seconds after there no changes in the DOM just after pressing a button that triggers a lot of changes.
An example with a button gotten via jQuery:
$someButton.on('click',function(){
setInterval(function(){
if( noChangesSinceLastTime()){
time += 100;
}
else{
time = 0;
}
if( time == 3000){
alert("3 seconds without changes!");
}
},100);
});
Assume that the click event on that button has some other binding that excecutes a series of functions for DOM manipulation.
How could I achieve something as the noChangesSinceLastTime()function?
More on my specific problem
I have an HTML+JS+CSS slideshow which works with many simultaneous clients in a network.
When a new client joins, he is automatically sent to the start of the current slide being watched by others.
What I want to do is that, just after it finishes loading the current slide, trigger the clicks necessary to sync the new client with others (since every click inside a slide triggers an animation step, and most slides have multiple steps).
I cannot add a callback in the JS slideware, since it's an obfuscated JS not made by me.
This is just pseudo code, but you could try something like this:
timer = setTimeout(function(){
alert("3 seconds without changes!");
}, 3000);
if(/*some change happens*/) {
clearTimeout(timer);
}
You could listen to all of the DOM Mutatation events and set a flag if any of those are were triggered.
Then in you interval function, you could check that flag and do whatever logic you want. =).
Regards,
I am popping up a dialog box when someone tries to navigate away from a particular page without having saved their work. I use Javascript's onbeforeunload event, works great.
Now I want to run some Javascript code when the user clicks "Cancel" on the dialog that comes up (saying they don't want to navigate away from the page).
Is this possible? I'm using jQuery as well, so is there maybe an event like beforeunloadcancel I can bind to?
UPDATE: The idea is to actually save and direct users to a different webpage if they chose cancel
You can do it like this:
$(function() {
$(window).bind('beforeunload', function() {
setTimeout(function() {
setTimeout(function() {
$(document.body).css('background-color', 'red');
}, 1000);
},1);
return 'are you sure';
});
});
The code within the first setTimeout method has a delay of 1ms. This is just to add the function into the UI queue. Since setTimeout runs asynchronously the Javascript interpreter will continue by directly calling the return statement, which in turn triggers the browsers modal dialog. This will block the UI queue and the code from the first setTimeout is not executed, until the modal is closed. If the user pressed cancel, it will trigger another setTimeout which fires in about one second. If the user confirmed with ok, the user will redirect and the second setTimeout is never fired.
example: http://www.jsfiddle.net/NdyGJ/2/
I know this question is old now, but in case anyone is still having issues with this, I have found a solution that seems to work for me,
Basically the unload event is fired after the beforeunload event. We can use this to cancel a timeout created in the beforeunload event, modifying jAndy's answer:
$(function() {
var beforeUnloadTimeout = 0 ;
$(window).bind('beforeunload', function() {
console.log('beforeunload');
beforeUnloadTimeout = setTimeout(function() {
console.log('settimeout function');
$(document.body).css('background-color', 'red');
},500);
return 'are you sure';
});
$(window).bind('unload', function() {
console.log('unload');
if(typeof beforeUnloadTimeout !=='undefined' && beforeUnloadTimeout != 0)
clearTimeout(beforeUnloadTimeout);
});
});
EDIT: jsfiddle here
Not possible. Maybe someone will prove me wrong... What code do you want to run? Do you want to auto-save when they click cancel? That sounds counter-intuitive. If you don't already auto-save, I think it makes little sense to auto-save when they hit "Cancel". Maybe you could highlight the save button in your onbeforeunload handler so the user sees what they need to do before navigating away.
I didn't think it was possible, but just tried this idea and it works (although it is some what of a hack and may not work the same in all browsers):
window.onbeforeunload = function () {
$('body').mousemove(checkunload);
return "Sure thing";
};
function checkunload() {
$('body').unbind("mousemove");
//ADD CODE TO RUN IF CANCEL WAS CLICKED
}
Another variation
The first setTimeout waits for the user to respond to the browser's Leave/Cancel popup. The second setTimeout waits 1 second, and then CancelSelected is only called if the user cancels. Otherwise the page is unloaded and the setTimeout is lost.
window.onbeforeunload = function(e) {
e.returnValue = "message to user";
setTimeout(function () { setTimeout(CancelSelected, 1000); }, 100);
}
function CancelSelected() {
alert("User selected stay/cancel");
}
window.onbeforeunload = function() {
if (confirm('Do you want to navigate away from this page?')) {
alert('Saving work...(OK clicked)')
} else {
alert('Saving work...(canceled clicked)')
return false
}
}
with this code also if user clicks on 'Cancel' in IE8 the default navigation dialog will appear.