TheYaXxE
TheYaXxE

Reputation: 4294

Trigger event every 2 minutes when typing

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.

Fiddle Demo

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

Answers (5)

jondro
jondro

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

Varinder
Varinder

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

Michal Brašna
Michal Brašna

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

Gabriele Petrioli
Gabriele Petrioli

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

florianmientjes
florianmientjes

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

Related Questions