Lukas Naujokaitis
Lukas Naujokaitis

Reputation: 421

How to simulate the space button like the real person on the keyboard using JS

I'd like to find out how can I simulate the space button click on the keyboard like a real person would do that. I have some examples here.

First one is using jsFiddle. jsFiddle is just to make things simpler, I'm gonna test it out and then use it in my project code. The links can be found below.

I've read about the new KeyboardEvent() constructor, however, I don't think it would fix my problem. Maybe I'm doing something wrong, but I need to simulate the space button press like it would be real.

I'm sure document.getElementById('test').value += ' '; isn't doing anything "realistic", it just changes the value of #text element. After examples, I'll show you how I'd like it to work with images.


Here is my example jsFiddle: https://jsfiddle.net/od5g4u43/.

Stacksnippet:

document.getElementById('test').addEventListener('keydown', function(ev) {
  document.getElementById('test').value += ' ';
});

(function() {
  var e = new Event('keydown');
  e.which = e.keyCode = 32; // 32 is the keycode for the space bar
  document.getElementById('test').dispatchEvent(e);
})();
<input id="test" type="text" value="opa!">

And my full project code can be found here: https://codepen.io/Kestis500/pen/ddbwpq.


  1. So, we just reloaded a page. Don't care about the different environment. It's my project code and you shouldn't care about any jQuery or JS stuff except the code in the jsFiddle or Stacksnippet.

    The same code as in the jsFiddle or Stacksnippet is in the middle of the codepen.com full code, inside "select" event.

    Again, you don't need to go there but if you want to test it out by yourself, go ahead.

enter image description here

  1. Enter the character "a" into the search box.

enter image description here

  1. document.getElementById('test').value += ' '; worked and now we have an extra space after the actual search box value. The results should change they didn't. It was done using code.

enter image description here

  1. Let's try the same thing but without document.getElementById('test').value += ' '; line or anything what's inside jsFiddle or Stacksnippet. I just removed the space generated by code like the real person (on the keyboard pressed the backspace when I was focused on the search box.

enter image description here

EDIT 3 Thank you, it worked! I just have a fresh fork of this code on the codepen here.

I've made some changes to your code so it works for my problem and instead of printing each character, now it prints and removes the space super quickly. setTimeout(..., 0); is because to wait until the JS Stack is clear.

function updateSearchField() {
  t0 = performance.now();
  $("#search").focus();
  //update the search field with a character and
  //trigger the keypress event for the autocomplete
  $("#search")
    .val($("#search").val() + " ")
    .keydown();
  t1 = performance.now();
}

setTimeout(function() {
  updateSearchField();

  setTimeout(function() {
    var $text = $("#search").val();
    $("#search").val($text.substring(0, $text.length - 1));
  }, t1 - t0);
  console.log(t1 - t0);
}, 0);

Explanation of this can be found here (video).

Upvotes: 0

Views: 3480

Answers (2)

Kyle Dodge
Kyle Dodge

Reputation: 934

You've got a few things going on here. First, you can't simply set the value as you are doing - what you want to do is set each character individually with a timeout between each update. This will give the appearance of a user typing. Secondly, you are using Jquery UI autocomplete which will require keypress events after each update to tell the autocomplete to refresh its search results. Here is a quick solution that solves what you are looking for.

  function showDemo() {
    //give focus to the search field
    $("#search").focus();

    //the search content split into a string array
    var characters = "anarchist symbolism".split("");
    //the time between each character keypress
    var timeout = 0;

    characters.forEach(function(character) {
      //setup a random keypress time in milliseconds to simulate a real user typing
      timeout += Math.floor(Math.random() * 670);

      setTimeout(function() {
        //update the search field for this character at this 
        //timeout interval
        updateSearchField(character);
      }, timeout);
    });
  }

  function updateSearchField(character) {
    //update the search field with a character and 
    //trigger the keypress event for the autocomplete
    $("#search")
      .val(function(i, val) {
        return val + character;
      })
      .keypress();

    //intialize a keydown event with any key code to setup the keypress listener
    var e = jQuery.Event("keydown");
    e.which = 32; 
    $("#search").trigger(e);
  }

You may also not want this to start immediately, especially with the animations you have in the codepen example. You may want to delay the start of this with a timeout:

//wait 4 seconds before initializing the demo. This can be anything,
//just to give the user time so it does not happen immediately
setTimeout(showDemo, 4000);

Here is a codepen fork of your example with this code to show the result: https://codepen.io/kyledodge/pen/xYKmmy

Upvotes: 1

Daniel Beck
Daniel Beck

Reputation: 21485

Dispatched events don't behave the same way that real user actions do -- they only fire the event (so that event listeners can respond to them). A dispatched keydown event on an input field does not change the value of the field, it just fires the event itself.

You need to change the value of the field directly (just as you're doing with the document.getElementById('test').value += ' ';) and then dispatch whichever event or events your remaining code is watching for to update the autocomplete results.

Upvotes: 3

Related Questions