Reputation: 4294
I'm looking for a way to trigger an event for every 2 minutes when you are typing, in any input
or textarea
.
If you then stops typing, the event will happen one more time, in the remaining time of the 2 minutes. (Hope you understand)
It is very much the same function as the one WordPress are using, when a draft is autosaved once per minute.
I am no Wordpress expert, so I can't find the function they are using in their scripts.
This is what I've got so far:
$("input, textarea").keyup(function () {
var minutes = 2;
var time = minutes * 60000;
setInterval(function () {
// Do event here
}, time);
});
It doesn't work that well. If you are typing many characters the event will be triggered multiple times right after each others. Also the event is triggered even if you are clicking on Ctrl, the arrow keys..... which is not intended.
And I can't seem to find a good way to detect, when a user has stopped typing.
I've found this code, but I don't know how to use it, along with the other code I'm using:
//setup before functions
var typingTimer; //timer identifier
var doneTypingInterval = 5000; //time in ms, 5 second for example
//on keyup, start the countdown
$('#myInput').keyup(function(){
typingTimer = setTimeout(doneTyping, doneTypingInterval);
});
//on keydown, clear the countdown
$('#myInput').keydown(function(){
clearTimeout(typingTimer);
});
//user is "finished typing," do something
function doneTyping () {
//do something
}
Can someone please help me?
Upvotes: 1
Views: 651
Reputation: 619
First we want to be able to tell if the user is typing or he as stopped. We can do that by checking every couple of seconds when the last key stroke was. If it's been, let's say 30sec. since the last one we can assume that he's not typing. The second interval will autosave every two minutes and if the user is not typing anymore it will clear itself.
var isTyping = false;
var lastKeystroke = null;
var autosaveInterval = null;
$('#myInput').keyup(function() {
lastKeystroke = Date.now();
if (autosaveInterval == null) {
startAutosaveInterval();
}
});
setInterval(function() {
if (Date.now() - lastKeystroke > 30000) { // 30 sec. since last key stroke
isTyping = false;
} else {
isTyping = true;
}
}, 2000);
function startAutosaveInterval() {
autosaveInterval = setInterval(function() {
// do whatever
if (!isTyping) {
clearInterval(autosaveInterval);
autosaveInterval = null;
}
}, 2 * 60 * 1000); // every two minutes
}
I have not tested this code. but you should be able to take it from here.
Upvotes: 0
Reputation: 2664
Edit http://jsfiddle.net/Varinder/RWBYH/2/
//setup before functions
var typingTimer = null; //timer identifier
var doneTypingInterval = 2000; //time in ms, 2 second for example
//on keyup, start the countdown
$('input').keyup(function(){
clearTimeout(typingTimer); // clearing timer
typingTimer = setTimeout(doneTyping, doneTypingInterval);
});
//on keydown, clear the countdown
$('input').keydown(function(){
clearTimeout(typingTimer);
});
//user is "finished typing," do something
function doneTyping() {
alert("Saving draft");
}
The sample code provided works just fine: http://jsfiddle.net/Varinder/RWBYH/1/
//setup before functions
var typingTimer; //timer identifier
var doneTypingInterval = 5000; //time in ms, 5 second for example
//on keyup, start the countdown
$('input, textarea').keyup(function(){
typingTimer = setTimeout(doneTyping, doneTypingInterval);
});
//on keydown, clear the countdown
$('input, textarea').keydown(function(){
clearTimeout(typingTimer);
});
//user is "finished typing," do something
function doneTyping () {
alert("Saving draft");
}
Upvotes: 0
Reputation: 2323
You need something called time based event throttling.
Demo on http://jsfiddle.net/Gobie/LUv2u/
// taken from Remy Sharp's page
function throttle(fn, threshhold, scope) {
threshhold || (threshhold = 250);
var last,
deferTimer;
return function () {
var context = scope || this;
var now = +new Date,
args = arguments;
if (last && now < last + threshhold) {
// hold on to it
clearTimeout(deferTimer);
deferTimer = setTimeout(function () {
last = now;
fn.apply(context, args);
}, threshhold);
} else {
last = now;
fn.apply(context, args);
}
};
}
// actual code
var interval = 2 * 60 * 1000; // 2min
$("input, textarea").keyup(throttle(function () {
console.log(new Date);
}, interval));
Upvotes: 0
Reputation: 196296
You should not use setInterval
but setTimout
and spawn a new one only after the first has been run..
var saveTimer = null,
minutes = 2,
time = minutes*60000;
$("input, textarea").keyup(function () {
if (!saveTimer){
saveTimer = setTimeout(function() {
alert("Hello");
saveTimer = null;
}, time);
}
});
Demo at http://jsfiddle.net/gaby/h9pe3/
Upvotes: 2
Reputation: 146
You could set a boolean to check for new user input like I did in this fiddle
var hasTyped = false;
$("input, textarea").keyup(function () {
hasTyped = true;
});
var minutes = 0.1;
var time = minutes*60000;
setInterval(function() {
if(hasTyped){
alert("Hello");
hasTyped = false;
}
}, time);
The other code you posted works a bit different: instead of running every 2 minutes, it will run 5 seconds after you stopped typing. For autosave this would be a good solution as well, depending on your preference.
Upvotes: 0