cyber_phoenEX
cyber_phoenEX

Reputation: 39

JavaScript 'keyup' and 'keydown' event listeners only trigger once

I am a novice JavaScript programmer- this is my first project in the language. I am currently attempting to run a makeshift "timer" that triggers when a key is pressed down (keydown) and ends when the key is released (keyup). For testing purposes, I also have each function print a statement whenever they trigger. Unfortunately, I can only get the event listener to trigger once. I want the script to run and respond to input whenever the user hits any key. Honestly, the "timer" is a placeholder for a larger project- getting the keydown/keyup events to run each time the user presses a key is what matters instead of only on the initial press.

I have tried a lot of different tactics already, and I will continue to research the issue as I await a response. At first, I suspected the issue was because I set the JavaScript in the head part of the html document, before it loaded, but moving it to the body did not fix the issue. I worried that it was because I was not writing a new line each time, but changing to document.writeln did not help. I've tried a few simple forms of looping the code without success- I am currently researching how I would make the function recursive to see if that would help. I have also attempted loading the code into jquery to no avail (the JQuery one does not even trigger once). I have also done a little work with things like window.setInterval based on the research I've done on keylogging, but I don't fully understand what it does and have had no success.

// The initial script
<!DOCTYPE html>
<html>

  <head>
    <script type="text/javascript">
    var start, finish, diff;

    // Adds event listeners
    document.addEventListener('keydown',startTimer);
    document.addEventListener('keyup',endTimer);

    // Runs on keydown, simply stores a new date
    function startTimer(e){
        start = new Date();
    }

    // Runs on keyup, stores a new date (time in milliseconds since 
epoch),
    // then takes and prints the difference between the two. 
    function endTimer(e){
        finish = new Date();
        diff = finish - start;
        document.write(diff);
    }

    </script>
  </head>

  <body>
  </body>
</html>

// "Most stable" version, utilizing onkeyup/onkeydown and writeln
<!DOCTYPE html>
<html>

  <head>

  </head>

  <body>
    <script type="text/javascript">
    var start, finish, diff;

      document.onkeydown = function(e){
          start = new Date();
          document.writeln(start);
      }

      document.onkeyup = function(e){
          finish = new Date();
          diff = finish - start;
          document.writeln(finish);
          document.writeln(diff);
      }
    </script>
  </body>
</html>

// JQuery version
<!DOCTYPE html>
<html>

  <head>

  </head>

  <body>
    <script src="jquery-3.4.1.min.js">
    var start, finish, diff;

    $("q").keydown(function(){
      start = new Date();
      document.writeln(start);
    });

    $("w").keyup(function(){
      finish = new Date();
      diff = finish - start;
      document.writeln(finish);
      document.writeln(diff);
    });

    </script>
  </body>
</html>

I expected the "website" to print out the precise stored date each time I press down a key, then print out a new date when I release it and the difference between the two. Instead, when I first press down a key it prints out the information, then prints nothing no matter what I do.

I will note that the JQuery one currently does not even print out the first message- I am doing more research as to why- I have only done very lite JQuery research.

Thanks for the help.

Upvotes: 2

Views: 2544

Answers (2)

Don M
Don M

Reputation: 986

I think you want something like this.

// The initial script
<!DOCTYPE html>
<html>

 <head>
   <script type="text/javascript">
    var start, finish, diff;

// Adds event listeners
document.addEventListener('keydown',startTimer);
document.addEventListener('keyup',endTimer);

// Runs on keydown, simply stores a new date
function startTimer(e){
    console.log('down', e)
            start = new Date();
        }

        // Runs on keyup, stores a new date (time in milliseconds since 
//  epoch),
        // then takes and prints the difference between the two. 
        function endTimer(e){
      console.log('up', e)
           finish = new Date();
            diff = finish - start;
          console.log('diff', diff)
            document.querySelector('body').innerHTML = (diff);
        } 

   </script>
  </head>

 <body>
 </body>
</html>

The problem is when you tell endTimer to write the amount of time that has past:

document.write(diff)

you are writing to the root of the document and not an element in the document. Once that is overwritten you do not have a DOM object to have an event from.

Upvotes: 1

Anis R.
Anis R.

Reputation: 6902

As commented by @JaromandaX, the issue is with using document.writeln() inside your event handler. Using console.log() instead fixes the issue.

Explanation: Using document.write() after the page has loaded wipes out the current document, and replaces the contents with whatever string is passed. Credits

var start, finish, diff;

      document.onkeydown = function(e){
          start = new Date();
          console.log(start);
      }

      document.onkeyup = function(e){
          finish = new Date();
          diff = finish - start;
          console.log(finish);
          console.log(diff);
      }
<!--"Most stable" version, utilizing onkeyup/onkeydown and writeln-->
<!DOCTYPE html>
<html>

  <head>

  </head>

  <body>
  </body>
</html>

Upvotes: 0

Related Questions