I have a form with an <input type=text /> and I want to call a javascript function after 5 seconds of the last key press, and every time a new key is pressed, this timer should reset and only call the function after 5 seconds.
How can I do this?
I'm using jQuery.
thanks!
Something like this should get you started:
var timeout;
$('input[type=text]').keypress(function() {
if(timeout) {
clearTimeout(timeout);
timeout = null;
}
timeout = setTimeout(myFunction, 5000)
})
This answer is great, but remember that you need to enable this code after the documents loads and after the function loads to clear the timeout.
Here is the complete code:
var timeout;
$(document).ready(function(){
$('input[type=text]').keypress(function() {
if(timeout) {
clearTimeout(timeout);
timeout = null;
}
timeout = setTimeout(myFunction, 5000);
});
});
var myFunction = new function() {
alert('myFunction is running');
clearTimeout(timeout); // this way will not run infinitely
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
Although it doesn't use jQuery, you could also have a look at the debouncing function described here.
Steve
Related
I have two quantity selector buttons.
After the user clicks in any of these buttons (increasing or decreasing quantity), I need to run a function.
But the user can click several times in a row, and I want to execute the function only once.
Like, wait 1 second after each click to run the function. If within this 1 second the user clicks the button again, reset the timer and wait for another second to run the function. When the user doesn´t click again within 1 second, run the function.
What´s the best way to do that in vanilla javascript?
You just need to start a 1 second timer and reset it whenever the button click happens.
let timer
function handleClick() {
clearTimeout(timer)
timer = setTimeout(doSomething, 1000);
}
function doSomething() {
let div = document.getElementById("list")
let p = document.createElement("p")
p.textContent = "1 second passed without a click"
div.append(p)
}
<!DOCTYPE html>
<html>
<body>
<button onclick="handleClick()">Click me</button>
<div id=list></div>
</body>
</html>
I see two solutions:
If each click triggers some request, then disable button until the request is completed
Use throttling for the function invoke. You can use RxJS's throttle or you can write your own throttle method.
https://medium.com/nerd-for-tech/debouncing-throttling-in-javascript-d36ace200cea
You described a classic debounce technique. Here is an implementation:
Taken from https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore#_debounce
Another way is to dig into Lodash source codes and copy it from there
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
clearTimeout(timeout);
timeout = setTimeout(function() {
timeout = null;
if (!immediate) func.apply(context, args);
}, wait);
if (immediate && !timeout) func.apply(context, args);
};
}
// Avoid costly calculations while the window size is in flux.
jQuery(window).on('resize', debounce(calculateLayout, 150));
Here is a nice article and a playground about it https://css-tricks.com/debouncing-throttling-explained-examples/
You can try this in Vanilla JS :
const btn = document.querySelector('#btn');
const callback = event => {
console.log(event);
clearInterval(interval);
}
let interval;
btn.addEventListener('click', event => {
clearInterval(interval);
interval = setInterval( () => callback(event), 1000);
});
And the HTML :
<html>
<body>
<button id="btn">test</button>
</body>
</html>
That way you can pass the event instance to your callback.
My objective is to keep a user in a view as long as he/she keeps clicking a button within a certain lapse.
I'm using Rails and was exploring a solution via an embedded JS in the pertinent view.
So far I'm able to set a time after which the user will be redirected to root path with the following script:
var delayedRedirect = function (){
window.location = "/";
}
var delay = 10000;
$(document).ready(function() {
setTimeout('delayedRedirect()', delay);
});
I've been trying to write a function that resets the value of 'delay'or that calls the setTimeoutFunction again.
$('#btn-persist').click(function() {
delay = 3000;
// or calling again setTimeout('delayedRedirect()', delay);
});
But I noticed that changing the variable won't affect the setTimeout function that has already been called.
I've also tried to use the clearTimeout function as below without success
var delayedRedirect = function (){
window.location = "/persists";
}
var delay = 3000;
var triggerRedirect = function() { setTimeout('delayedRedirect()', delay);
}
var stopRedirect = function (){
clearTimeout(triggerRedirect);
}
$(document).ready(function() {
triggerRedirect();
$('#btn-persist').click(function() {
stopRedirect();
});
});
I wonder why this may not be working and if there's any other way to stop the execution of the setTimeout function that has already been called so I can call it again to effectively reset the time to the original value of 'delay'.
At the same time, I don't want to stop any other JS functions that are running in parallel.
Do you see a better solution to achieve this?
The main problem why clearTimeout is not working. because you are clearing a anonymous function instead of a setTimeout variable
change this
var triggerRedirect = function() { setTimeout('delayedRedirect()', delay);
}
to this
var triggerRedirect = setTimeout('delayedRedirect()', delay);
Edit:
also change this (if you want to restart the inactive redirect trigger)
$('#btn-persist').click(function() {
stopRedirect();
});
to this
$('#btn-persist').click(function() {
stopRedirect();
triggerRedirect();
});
I have 4 div´s each contains an image item and a select list of 4 div-id. I want to refresh the images simultaneously by changing the source of each image every 2 seconds.
I'm using setInterval() for each image and the problem is when I must stop all the timers at the same time.
Should I make a timer variable per div/img?
$(.div-id option:selected).each(function(){
var timer = setInterval(function(){
$(.div-id img).attr("src", "new-source-path");
},2000);
});
How can I stop all the active timers at once without stopping every timer Id?
Is there any solution with setTimeout() or any plugin to do that?
I'd opt for a single timer that loops through all images. Then when the timer isn't needed anymore I can just discard the single timer.
var timer = setInterval(swapImages, 2000);
function swapImages() {
$(.div-id option:selected).each(function(){
$(.div-id img).attr("src", "new-source-path");
});
}
// some time later
clearInterval(timer);
PS. I assume that your code is some pseudo code so I copied your namings
The end solution
function swapImages() {
$(".div-id-list option:selected").each(function () {
var url = "new-source-path";
$("#div-id img").attr("src", url);
});
}
function stopTimer() {
clearInterval(timer);
}
$(".div-id-list").on("change", function () {
stopTimer();
timer = setInterval(swapImages, 2000);
});
Thanks to donnywals !
I got this auto form submitter as I search the internet. Though I want it to execute the submission in a certain period of time. Like perhaps after 5 or 10 seconds.
<script type="text/javascript">
function formAutoSubmit () {
var frm = document.getElementById("31926767765874");
frm.submit();
}
setTimeout(function() { formAutoSubmit(); } , 5000);
</script>
Take a look, and read up on, JavasScript Timing Events. You can simply wrap formAutoSubmit() in a timer, like so:
<script type="text/javascript">
function formAutoSubmit() {
var frm = document.getElementById("31926767765874");
frm.submit();
}
var timeout = 2000; //2 seconds or 2000 ms
setTimeout(function()
{
formAutoSubmit();
}, timeout);
</script>
Caveat: this can be a nuisance for the user experience, so tread carefully.
If you want to run after 5 seconds:
setTimeout(function() { formAutoSubmit(); } , 5000);
If you want to run it each 5 seconds:
setInterval(function() { formAutoSubmit(); } , 5000);
Use setTimeout
setTimeout(formAutoSubmit, 10000);
That's 10000 ms (or 10s)
I have an unusual problem. I'm using the following script to check for internet connection using navigator.onLine. If there is internet connection, the page will be refreshed every 15 seconds. If there isn't any internet connection, the page will use innerHTML to display a message.
<script type="text/javascript">
setInterval(function () {
if (navigator.onLine) {
var myInterval = setInterval(function(){window.location.href = "Tracker.html";},15000);
} else {
clearInterval(myInterval);
var changeMe = document.getElementById("change");
change.innerHTML = "<big><font face='Arial' color='#ffffff' size='2'><center>OFFLINE</big><br>No internet connection</font></center>";
}
}, 250);
</script>
My problem is, once there is no internet connection, the message will be displayed, BUT the page would still be refreshed one last time. I'm trying to avoid this, by using clearInterval(myInterval); in the else part of the code, however it won't work.
Any suggestions?
To refresh the page at 15 second intervals (provided that a connection is present), use:
function refresh() {
if(navigator.onLine)
window.location.href = "Tracker.html";
else{
var changeMe = document.getElementById("change");
change.innerHTML = "<big><font face='Arial' color='#ffffff' size='2'><center>OFFLINE</big><br>No internet connection</font></center>";
setTimeout(refresh, 250);
}
}
setTimeout(refresh, 15000);
At the end of 15 seconds, this checks whether a connection is present. If there is, it refreshes the page. If there isn't, it proceeds to check every 250 milliseconds afterwards until the user is reconnected, at which point it refreshes the page.
The net result is that the script refreshes the page as soon as possible after a minimum of 15 seconds have elapsed.
Here is a demonstration: http://jsfiddle.net/JGEt9/show
Whenever the outer interval callback is executed, a new myInterval variable is created and the previous one is lost (it goes out of scope because the callback terminates).
You have to persist the value of the variable between function calls by declaring it outside of the function. You also have to make sure that you are not creating another timeout if one is already running.
var timeout = null;
setInterval(function () {
if (navigator.onLine) {
if (timeout === null) {
timeout = setInterval(function(){window.location.href = "Tracker.html";},15000);
}
} else {
clearTimeout(timeout);
timeout = null;
// ...
}
}, 250);
You need to declare myInterval outside of the if statement. You should only need the refresh code once too. Something like this:
var myInterval = setTimeout(function(){window.location.href = "Tracker.html";},15000);
setInterval(function () {
if (!navigator.onLine) {
clearTimeout(myInterval);
var changeMe = document.getElementById("change");
changeMe.innerHTML = "<big><font face='Arial' color='#ffffff' size='2'><center>OFFLINE</big><br>No internet connection</font></center>";
}
}, 250);
Here you set the refresh interval and continually check to see if the browser is offline, and if it is, you remove the timer and do your cleanup code. I also changed the refresh code to use setTimeout instead of interval because it only happens once.
Another issue is you create changeMe but then try to use change. change doesn't exist. I fixed that in my example as well.
Note: This will not resume refreshing once connection is regained. See Felix Kling's answer.