javascript 2.4.3 Клавиатура: keydown и keyup

Прежде чем перейти к клавиатуре, обратите внимание, что на современных устройствах есть и другие способы «ввести что-то». Например, распознавание речи (это особенно актуально на мобильных устройствах) или Копировать/Вставить с помощью мыши.

Поэтому, если мы хотим корректно отслеживать ввод в поле <input>, то одних клавиатурных событий недостаточно. Существует специальное событие input, чтобы отслеживать любые изменения в поле <input>. И оно справляется с такой задачей намного лучше. Мы рассмотрим его позже в главе События: change, input, cut, copy, paste.

События клавиатуры же должны использоваться, если мы хотим обрабатывать взаимодействие пользователя именно с клавиатурой (в том числе виртуальной). К примеру, если нам нужно реагировать на стрелочные клавиши Up и Down или горячие клавиши (включая комбинации клавиш).

События keydown и keyup

Событие keydown происходит при нажатии клавиши, а keyup – при отпускании.

event.code и event.key

Свойство key объекта события позволяет получить символ, а свойство code – «физический код клавиши».

К примеру, одну и ту же клавишу Z можно нажать с клавишей Shift и без неё. В результате получится два разных символа: z в нижнем регистре и Z в верхнем регистре.

Свойство event.key – это непосредственно символ, и он может различаться. Но event.code всегда будет тот же:

Клавишаevent.keyevent.code
Zz (нижний регистр)KeyZ
Shift+ZZ (Верхний регистр)KeyZ

Если пользователь работает с разными языками, то при переключении на другой язык символ изменится с "Z" на совершенно другой. Получившееся станет новым значением event.key, тогда как event.code останется тем же: "KeyZ".«KeyZ» и другие клавишные коды

У каждой клавиши есть код, который зависит от её расположения на клавиатуре. Подробно о клавишных кодах можно прочитать в спецификации о кодах событий UI.

Например:

  • Буквенные клавиши имеют коды по типу "Key<буква>""KeyA""KeyB" и т.д.
  • Коды числовых клавиш строятся по принципу: "Digit<число>""Digit0""Digit1" и т.д.
  • Код специальных клавиш – это их имя: "Enter""Backspace""Tab" и т.д.

Существует несколько широко распространённых раскладок клавиатуры, и в спецификации приведены клавишные коды к каждой из них.

Можно их прочитать в разделе спецификации, посвящённом буквенно-цифровым клавишам или просто нажмите нужную клавишу на тестовом стенде выше и посмотрите.Регистр важен: "KeyZ", а не "keyZ"

Выглядит очевидно, но многие всё равно ошибаются.

Пожалуйста, избегайте опечаток: правильно KeyZ, а не keyZ. Условие event.code=="keyZ" работать не будет: первая буква в слове "Key" должна быть заглавная.

А что, если клавиша не буквенно-цифровая? Например, Shift или F1, или какая-либо другая специальная клавиша? В таких случаях значение свойства event.key примерно тоже, что и у event.code:

Клавишаevent.keyevent.code
F1F1F1
BackspaceBackspaceBackspace
ShiftShiftShiftRight или ShiftLeft

Обратите внимание, что event.code точно указывает, какая именно клавиша нажата. Так, большинство клавиатур имеют по две клавиши Shift: слева и справа. event.code уточняет, какая именно из них была нажата, в то время как event.key сообщает о «смысле» клавиши: что вообще было нажато (Shift).

Допустим, мы хотим обработать горячую клавишу Ctrl+Z (или Cmd+Z для Mac). Большинство текстовых редакторов к этой комбинации подключают действие «Отменить». Мы можем поставить обработчик событий на keydown и проверять, какая клавиша была нажата.

Здесь возникает дилемма: в нашем обработчике стоит проверять значение event.key или event.code?

С одной стороны, значение event.key – это символ, он изменяется в зависимости от языка, и если у пользователя установлено в ОС несколько языков, и он переключается между ними, нажатие на одну и ту же клавишу будет давать разные символы. Так что имеет смысл проверять event.code, ведь его значение всегда одно и тоже.

Вот пример кода:

document.addEventListener('keydown', function(event) {
  if (event.code == 'KeyZ' && (event.ctrlKey || event.metaKey)) {
    alert('Отменить!')
  }
});

С другой стороны, с event.code тоже есть проблемы. На разных раскладках к одной и той же клавише могут быть привязаны разные символы.

Например, вот схема стандартной (US) раскладки («QWERTY») и под ней немецкой («QWERTZ») раскладки (из Википедии):

Для одной и той же клавиши в американской раскладке значение event.code равно «Z», в то время как в немецкой «Y».

Буквально, для пользователей с немецкой раскладкой event.code при нажатии на Y будет равен KeyZ.

Если мы будем проверять в нашем коде event.code == 'KeyZ', то для людей с немецкой раскладкой такая проверка сработает, когда они нажимают Y.

Звучит очень странно, но это и в самом деле так. В спецификации прямо упоминается такое поведение.

Так что event.code может содержать неправильный символ при неожиданной раскладке. Одни и те же буквы на разных раскладках могут сопоставляться с разными физическими клавишами, что приводит к разным кодам. К счастью, это происходит не со всеми кодами, а с несколькими, например KeyAKeyQKeyZ (как мы уже видели), и не происходит со специальными клавишами, такими как Shift. Вы можете найти полный список проблемных кодов в спецификации.

Чтобы отслеживать символы, зависящие от раскладки, event.key надёжнее.

С другой стороны, преимущество event.code заключается в том, что его значение всегда остаётся неизменным, будучи привязанным к физическому местоположению клавиши, даже если пользователь меняет язык. Так что горячие клавиши, использующие это свойство, будут работать даже в случае переключения языка.

Хотим поддерживать клавиши, меняющиеся при раскладке? Тогда event.key – верный выбор.

Или мы хотим, чтобы горячая клавиша срабатывала даже после переключения на другой язык? Тогда event.code может быть лучше.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *