Слушатели событий JavaScript «keyup» и «keydown» запускаются только один раз

Я начинающий программист на JavaScript — это мой первый проект на языке. В настоящее время я пытаюсь запустить импровизированный «таймер», который срабатывает при нажатии клавиши (нажатие клавиши) и заканчивается при отпускании клавиши (нажатие клавиши). В целях тестирования я также заставляю каждую функцию выводить оператор всякий раз, когда они срабатывают. К сожалению, я могу заставить прослушиватель событий запускаться только один раз. Я хочу, чтобы скрипт запускался и реагировал на ввод всякий раз, когда пользователь нажимает любую клавишу. Честно говоря, «таймер» — это заполнитель для более крупного проекта: важно, чтобы события keydown/keyup запускались каждый раз, когда пользователь нажимает клавишу, а не только при первом нажатии.

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

// 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 - он добавляет прослушиватель событий keydown для элементов, имя тега которых 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 или Java System.out.println. Я очень новичок в веб-разработке - 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