Doug Fir
Doug Fir

Reputation: 21322

Trigger function when someone has stopped typing for 1 second

I have an input field which generates auto suggestions when someone starts typing. The user does not need to blur or hit a submit button for the suggestions to appear.

When someone has stopped typing I would like to run a function for tracking which products were shown to the user, along with the string of text currently in input field.

I added an 'input' event listener but I cannot get my logic right.

I want to doStuff() if it has been at least 1 second since the previous input event. Trouble is that my script is firing when a user starts typing not after since it's based on 'change' event listener.

And I'm thinking there must be a more logical way than I'm doing now.

Also I'm worried that 'input' event is impacting the users browser since it's running on every keystroke, maybe there's a better way?

Reluctantly showing my code block below even though it does not make much sense and is one of my weaker scripting moments, more showing that I have been trying different things. Would prefer a solution that ignores the insane logic I have been using.

I want to doStuff(e) when a user has 'stopped entering text in input' which is not an exact definition. When is a user considered to have stopped typing? For now I'm saying 1 second.

Don't want to use change event since it misses a lot of events where the user does not blur.

Prefer pure JS.

  var input = document.querySelector('#search_input');
  var newinput;
  var lastinput;
  var diff;

        input.addEventListener('input', function(e) {

          newinput = new Date();
          if(!lastinput) {
            lastinput = new Date()
          }
          diff = newinput - lastinput;
          if(diff > 500 && diff < 2000) {
            doStuff(e)
          }

          lastinput = newinput;

        }, false);

Upvotes: 3

Views: 1297

Answers (2)

Soviut
Soviut

Reputation: 91714

The technique is sometimes called "debouncing". While plenty of libraries like Underscore or Lodash have this, it can be accomplished fairly easily in pure javascript. It wraps a function that will be called when the debounce time is exceeded. It involves using setTimeout() and clearing and resetting the timeout each time an event is fired on the input. If there is a delay in the events and the timeout is exceeded, the debounced function finally fires.

From David Walsh's blog post:

function debounce(func, wait, immediate) {
    var timeout;
    return function() {
        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            if (!immediate) func.apply(context, args);
        };
        var callNow = immediate && !timeout;
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
        if (callNow) func.apply(context, args);
    };
};

And to use it:

var myEfficientFn = debounce(function() {
    // All the taxing stuff you do
}, 250);

element.addEventListener('keyup', myEfficientFn);

In your case, you'll want to add events to keyup, keydown, change, cut, copy, paste, etc.

element.addEventListener('keyup', myEfficientFn);
element.addEventListener('keydown', myEfficientFn);
element.addEventListener('change', myEfficientFn);
// etc...

Upvotes: 3

nnnnnn
nnnnnn

Reputation: 150080

You can use the input event listener together with setTimeout() and clearTimeout() as follows:

var timeoutID;

document.querySelector('#search_input').addEventListener('input', function(e) {
  clearTimeout(timeoutID);
  timeoutID = setTimeout(function() {
    alert("1 second has passed since any input was received.");
    // doStuff()
  }, 1000);
});
<input id="search_input">

The setTimeout() function queues up the function you pass it in the first argument to be executed after the specified number of milliseconds have passed. The clearTimeout() function cancel a currently scheduled timeout based on the id returned by setTimeout().

So the function I've shown above basically says that whenever an input event occurs, cancel any previously scheduled timeout and then create another. Thus the code in the inner function will only be run approximately 1 second after the user stops typing.

Upvotes: 9

Related Questions