Слушателите на събития на JavaScript „keyup“ и „keydown“ се задействат само веднъж

Аз съм начинаещ програмист на JavaScript - това е първият ми проект на езика. В момента се опитвам да стартирам импровизиран "таймер", който се задейства при натискане на клавиш (keydown) и завършва, когато клавишът бъде освободен (keyup). За целите на тестването, аз също карам всяка функция да отпечатва израз всеки път, когато се задейства. За съжаление мога да накарам слушателя на събития да се задейства само веднъж. Искам скриптът да се изпълнява и да отговаря на въвеждане всеки път, когато потребителят натисне произволен клавиш. Честно казано, "таймерът" е контейнер за по-голям проект - това, което има значение, е да се изпълняват събитията за натискане на клавиши/клавиши всеки път, когато потребителят натисне клавиш, а не само при първоначалното натискане.

Вече опитах много различни тактики и ще продължа да проучвам проблема, докато чакам отговор. Първоначално подозирах, че проблемът е, защото зададох JavaScript в заглавната част на html документа, преди да се зареди, но преместването му в тялото не реши проблема. Притесних се, че е защото не пиша всеки път нов ред, но смяната на document.writeln не помогна. Опитах няколко прости форми на зацикляне на кода без успех - в момента проучвам как да направя функцията рекурсивна, за да видя дали това ще помогне. Също така се опитах да заредя кода в jquery без резултат (JQuery дори не се задейства веднъж). Също така свърших малко работа с неща като window.setInterval въз основа на изследванията, които направих за keylogging, но не разбирам напълно какво прави и нямах успех.

// 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>

Очаквах "уебсайтът" да отпечатва точната съхранена дата всеки път, когато натисна клавиш, след което да отпечата нова дата, когато го пусна, и разликата между двете. Вместо това, когато за първи път натисна клавиш, той отпечатва информацията, след което не отпечатва нищо, независимо какво правя.

Ще отбележа, че JQuery понастоящем дори не отпечатва първото съобщение - правя повече проучвания за това защо - Направих само много леко проучване на JQuery.

Благодаря за помощта.


person cyber_phoenEX    schedule 19.06.2019    source източник
comment
не използвайте document.write или document.writeln - използвайте console.log - и вероятно ще работи   -  person Jaromanda X    schedule 20.06.2019
comment
кодът на jquery не работи, защото не знаете jquery ... $('q').keydown не добавя слушател на събития за ключа q - той добавя слушател на събития надолу за елементи, чието име на етикет е q ... т.е. нищо във вашия HTML   -  person Jaromanda X    schedule 20.06.2019
comment
@JaromandaX Благодаря за обратната връзка, знаех, че се отнася до името на елемента, но не съм сигурен как да присвоя име на всеки клавиш, който потребителят натиска - предполагам, че ще прочета малко. Колкото до първото ти твърдение: абсолютно съм съгласен. Както казах, това е първият ми път, когато използвам JavaScript, тъй като не знаех нищо за него, така че знаех точно 0 JQuery.   -  person cyber_phoenEX    schedule 20.06.2019
comment
document.write няма абсолютно нищо общо с jQuery - така че първият ми израз също няма нищо общо с jQuery :D   -  person Jaromanda X    schedule 20.06.2019
comment
@JaromandaX Имах предвид твърдението: кодът на jquery не работи, защото не знаете jquery, съжалявам, не го изясних, затова казах, че съм напълно съгласен и нямам опит с JQuery. Поне знам достатъчно, за да видя, че използвах document.write, преди да изтегля JQuery   -  person cyber_phoenEX    schedule 20.06.2019


Отговори (2)


Мисля, че искаш нещо подобно.

// 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>

Проблемът е, когато кажете на endTimer да напише времето, което е минало:

document.write(diff)

пишете в основата на документа, а не в елемент в документа. След като това бъде презаписано, вие нямате DOM обект, от който да имате събитие.

person user3738936    schedule 19.06.2019
comment
Ха, благодаря за обратната връзка! Ще тествам скоро и ще редактирам отговора си - не разбрах, че document.write е направил това - предполагам, че мислех за него като C++ cout или System.out.println на Java. Аз съм много нов в уеб разработката - person cyber_phoenEX; 20.06.2019
comment
Трябва да използвате performance.now() вместо new Date(). Освен това началната ви дата ще продължи да се нулира, когато клавишът е натиснат, освен ако не зададете някаква променлива на състоянието на false и след това нулирате само на true след keyup. - person Grant Noe; 20.06.2019
comment
@GrantNoe Чудесен въпрос, не се сетих за това - това вероятно обяснява странните числа, които получавах за разликата. По ирония на съдбата се опитвах да изгладя процеса на тестване, за да мога да работя върху същата грешка, която току-що открихте. ...Което сега мисля за това трябваше да ми каже, че проблемът е с document.write, защото работеше, когато нямах множество. Добре, предполагам, че погледът назад е 20/20. - person cyber_phoenEX; 20.06.2019

Както коментира @JaromandaX, проблемът е с използването на document.writeln() във вашия манипулатор на събития. Използването на console.log() вместо това коригира проблема.

Обяснение: Използването на document.write(), след като страницата се е заредила, изтрива текущия документ и заменя съдържанието с какъвто низ е предаден. Кредити

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>

person Anis R.    schedule 19.06.2019