Запретить многократную обработку события нажатия клавиши JavaScript при нажатой клавише

#javascript

#javascript

Вопрос:

У меня есть этот код:

 else if (e.keyCode == 32){
      fired = true;
  

В функции нажатия клавиши (я добавил код document.addEventListener). Теперь это работает просто отлично и делает именно то, что я хочу, чтобы оно делало. Но вот проблема: если вы удерживаете клавишу нажатой, она продолжает вызывать fired = true снова и снова, непрерывно, пока не будет выпущена. Я просто хочу, чтобы оно установило fired = true; один раз, даже если клавиша нажата.

Комментарии:

1. Вы могли бы реализовать отмену отмены события…

2. Из интересного смотрите эту страницу , на которой (среди других подробных сведений) отмечается, что keydown событие не повторяется автоматически в браузерах Gecko, отличных от Windows.

Ответ №1:

Редактировать: теперь это полностью поддерживается в каждом браузере. за исключением Internet Explorer

Если совместимость с браузером не является вашей главной заботой *, вы могли бы попробовать получить доступ к .repeat свойству KeyboardEvent , как описано здесь:
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat

Выполнив что-то подобное в вашей функции-обработчике:

 function keyDown (e) {
  if (e.repeat) { return }

  // do stuff here
}
  

вы могли бы избежать повторных нажатий клавиш.


*: на сайте MDN указано, что это работает в Firefox, и я успешно использовал его в Chrome, поэтому у двух основных браузеров не должно возникнуть проблем с этим

Комментарии:

1. Наконец-то чистое решение!

2. Я рад, что вам понравилось, оно тоже из Венгрии, так что вы можете почувствовать, что оно местного производства . 😀

Ответ №2:

     var fired = false;

    element.onkeydown = function() {

        if(!fired) {
            fired = true;
            // do something
        }
    };
  

Затем используйте событие onkeyup

     element.onkeyup = function() {
     fired = false;
    };
  

Комментарии:

1. Куда я должен поместить этот материал? Просто в новой функции или что-то в этомроде? (Извините, я вроде как новичок в JavaScript)

2. @Chris Использование addEventListener (для не старого IE) — правильный способ регистрации обработчиков. Дело в том, что var fired=false; должно выходить за пределы любой функции, чтобы оно могло быть общим для обеих (с помощью магии замыканий ).

Ответ №3:

Попробуйте это 🙂

Вы можете определить, где-либо еще в вашем скрипте не используется клавиша, просто определив, keydown является ли это true! Вы также можете выполнить дополнительный скрипт при нажатой клавише, заменив console.log(); на то, что вы хотите, чтобы было нажато при нажатой клавише.

Пожалуйста, скажите мне, можно ли это улучшить.

 var keydown = false;
window.addEventListener('keydown', function() {
  if (!keydown) {
    keydown = true;
    console.log('key down');
  }
  window.addEventListener('keyup', function() {
    keydown = false;
  });
});  

Ответ №4:

Решения, приведенные выше, не учитывают многократные нажатия клавиш (представьте игру, в которой пользователь может одновременно нажимать вверх и влево, но оба должны быть запущены только один раз). Мне нужно было универсальное решение для отключения повтора клавиш при многократном нажатии для ВСЕХ клавиш:

 // create an array with 222 (number of keycodes) values set to true
var keyEnabledArray = Array(222).fill(true);

document.onkeydown = function(e){
    // disable the key until key release
    if(keyEnabledArray[e.keyCode]) {
        keyEnabledArray[e.keyCode] = false;
    }
};

document.onkeyup = function(e){
    // enable the specific key on keyup
    keyEnabledArray[e.keyCode] = true;
}; 
  

Проверьте фрагмент ниже:

 // create an array with 222 true values
var keyEnabledArray = Array(222).fill(true);

document.onkeydown = function(e){
    // disable the key until key release
    if(keyEnabledArray[e.keyCode]) {
        keyEnabledArray[e.keyCode] = false;
        document.getElementById('console').innerHTML  = e.keyCode   '<br>';
    }
    
};

document.onkeyup = function(e){
    keyEnabledArray[e.keyCode] = true;
};  
 Press a key:
<div id='console'></div>  

Ответ №5:

Используйте keyup событие. Оно запускается при поднятии клавиши.

Комментарии:

1. Просто имейте в виду, что если вы пытаетесь перехватить ключи, используемые браузером, keyup это не позволит вам предотвратить действие по умолчанию (в большинстве случаев). Используйте этот сайт для получения информации о порядке запуска и о том, когда браузеры запускают свои собственные события.

Ответ №6:

Другой подход к решению этой проблемы (предложенный моим другом):

  1. Обратите внимание на временную метку, когда каждый раз происходит событие нажатия клавиши

  2. Вычислите разницу между текущей временной меткой (t2) и предыдущей временной меткой (t1)

  3. (a) Если разница меньше некоторого заранее определенного порога, то это второе нажатие клавиши (означает, что мы уже выполнили код, который должен произойти при этом событии). Следовательно, мы можем отказаться от повторного выполнения кода

    (b) Если разница превышает заданный порог, то это первое нажатие клавиши. Следовательно, мы бы выполнили код

Ответ №7:

Чтобы избежать повторного keydown события, заблокируйте его после запуска и разблокируйте с помощью keyup . Вам следует избегать того, чтобы переменная ‘fired’ была глобальной, поэтому используйте блок кода с ES6 или closure в более старой версии JS.

Для ES6:

 { let fired = false;    // code block to exclude 'fired' from global scope
    element.addEventListener('keydown', (e) => {
        // only accept key down when was released
        if(!fired) {
            fired = true;
            // check what key pressed...
            if (e.keyCode === 32) {
                // and do what you need with it
            }
        }
    });

    element.addEventListener('keyup', (e) => {
        fired = false;
    });
}
  

Для более старой версии JS используйте IIFE:

 (function(){
    let fired = false;
    element.addEventListener('keydown', function(e) {
        // only accept key down when was released
        if(!fired) {
            fired = true;
            // check what key pressed...
            if (e.keyCode === 32) {
                // and do what you need with it
            }
        }
    });

    element.addEventListener('keyup', function(e) {
        fired = false;
    });
})();
  

Ответ №8:

В отличие от решения выше из Венгрии, где вы, return false если e.repeat имеет значение true, в моем варианте использования мне потребовалось выполнить следующее, чтобы эффективно отключить событие onChange для ввода текста / текстовой области.

 function keyDown (e) {
  if(e.repeat) {
    e.preventDefault()
  }

  // do stuff here
}
  

Больший контекст моего варианта использования (в JSX):

 <textarea 
  ref={formulaInput}
  defaultValue={formulaDefinition.string}
  onDoubleClick={handleLock} 
  onKeyUp={handleUnlock}
  onKeyDown={(e) => {
    if(e.repeat) {
      e.preventDefault()
    }
  }}
  onKeyPress={(e) => {
    if(e.repeat) {
      e.preventDefault()
    }
  }}
  readOnly={!focusLock}
  onChange={handleChange} 
  className={`formula-input ${focusLock ? 'formula-input__locked' : ''}`}
  id='2'
></textarea>