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.
Related
A website shows a cookie consent after arround 1-2 seconds, if a user has not give a consent. That means, the consent is not in the source directly but in the dom after 1-2 seconds.
I have to detect if a user clicks on a button inside of the consent div. If I use the document ready function, the click is not detected. I have to use setInterval because setTimeout doesn't work. The reason is that another window has to be opened in the Consent and therefore I cannot use a fixed time as with a timeout.
The Consent div is sourrended by a div with the class name "cmp-consent". I check the dom with setInterval every 1800ms for that div. If the div is not existend after 1800ms the user has already given the consent and I clear the setInterval.
BUT:
If the div exists, it waits until the user clicks on the second button in the consent header. When this click is made, another click is made and the window is closed. This is working very well.
The problem is, if a user does not click this button (consent-header button: eq (1)) immediately, the setInterval will of course continue to run. You can see the counter in front of the console.log is increasing. If a user then clicks the button, the subsequent clicks are carried out as often as there is a setInverval. This takes too long if a user waits, for example, longer then a minute. The question is, how do you manage that an action is only carried out once in a setInterval.
Here is my script:
var userConsent = window.setInterval(function() {
if ($(".cmp-consent")[0]){
console.log('consent exists');
$( ".consent-header button:eq(1)" ).click(function(){
console.log('User clicked the button');
$(".primary button").click();
$(".close-icon").click();
window.clearInterval(userConsent);
});
} else {
console.log('consent given, remove interval');
window.clearInterval(userConsent);
}
}, 1800);
Here is a working example of #cloned's suggustion.
document.addEventListener("click", function(e) {
for (var target=e.target; target && target!=this; target=target.parentNode) {
// loop parent nodes from the target to the delegation node
if (target.matches('.consent-header')) {
handler.call(target, e);
break;
}
}
}, false);
function handler() {
console.log('do stuff');
}
<div class="consent-header">
<button>I agree</button>
</div>
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 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.
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.
I need to invoke an event (for example - display alert) if a user presses on a link (not clicks) - and I don't want it to redirect him to another page. In other words - when a user clicks a link - everything is as usual but when the user presses the link, just the event happens (the alert is displayed) and the user will stay in my page. Is this possible?
By saying press I mean that a user presses on a link for at least one second.
Thanks.
After you refined your question, this code does what you are looking for:
<script>
var timeout;
function onMouseDown(){
timeout = window.setTimeout("alert(1)",1000);
}
function onMouseUp(){
window.clearTimeout(timeout);
}
</script>
click
Notes:
The return false causes the href not to be executed,
The timeout set and clear makes sure that a press of less than a second, won't fire the event
This will fire the alert if the user presses and holds the mouse over 1 second (1000 ms) on the link.
Define press.
You probably want to use either the mousedown or keypress event, depending on what you mean. (The latter case would probably involve checking the event to make sure it was the enter key that was used)
What I understood is that you want:
user pressed the link -> fire an action, but don't redirect the browser
User clicks the link (mouse up over the same object where you pressed the button) -> redirect to a different page
The following code might help
<html>
<head>
<script type="text/javascript">
function mouse_pressed(){
alert('pressed button');
}
function goToLink(url){
window.location = url;
}
</script>
</head>
<body>
<label onclick="goToLink('http://www.google.com');" onmousedown="mouse_pressed();" >text</label>
<body>
</html>
In Jquery you can do this in a simple way.
$("a").live('click',function(){
event.preventDefault();
});