События клавиатуры

Объекты KeyboardEvent описывают работу пользователя с клавиатурой. Каждое событие описывает клавишу; тип события (keydown, keypress или keyup) определяет произведённый тип действия.

Примечание: KeyboardEvent сообщит только о том, что на клавише произошло событие. Когда вам нужно обрабатывать ввод текста, то вместо него используйте "HTML5 input"-событие. Например, если пользователь вводит текст рукописным способом, предположим с планшета, то события клавиш могут не возникать.

keydown
Событие происходит, когда нажата клавиша на клавиатуре над элементом, но ещё не отпущена.
keypress
Событие происходит, когда пользователь нажал клавишу на клавиатуре над элементом.
keyup
Событие происходит, когда нажатая клавиша на клавиатуре над элементом перешла в состояние отпущено.

Свойства объекта KeyboardEvent

altKey Возвращает true, если нажата клавиша ALT.
ctrlKey Возвращает true, если нажата клавиша CTRL.
shiftKey Возвращает true, если нажата клавиша SHIFT.
metaKey Возвращает true, если нажата клавиша META.
charCode Содержит код Юникода сгенерированного печатного символа для события keypress.
code Определяет физическое расположение нажатой клавиши на клавиатуре
key Возвращает строку, представлающее значение клавиши, на которой возникло событие.
keyCode Возвращает виртуальный код нажатой клавиши.
locale Определяет язык для событий клавиатуры и событий textinput.
location Определяет местоположение нажатой клавиши для событий клавиатуры.
which Возвращает виртуальный код нажатой клавиши.

События keydown и keyup

События keydown/keyup происходят при нажатии/отпускании клавиши и позволяют получить её скан-код в свойстве keyCode.

Скан-код клавиши одинаков в любой раскладке и в любом регистре. Например, клавиша z может означать символ "z", "Z" или "я", "Я" в русской раскладке, но её скан-код будет всегда одинаков: 90.

В действии:

<input onkeydown="this.nextSibling.innerHTML = event.keyCode"> <b></b>

Скан-коды

Для буквенно-цифровых клавиш есть очень простое правило: скан-код будет равен коду соответствующей заглавной английской буквы/цифры.

Например, при нажатии клавиши S (не важно, каков регистр и раскладка) её скан-код будет равен "S".charCodeAt(0).

Для других символов, в частности, знаков пунктуации, есть таблица кодов, которую можно взять, например, из статьи Джона Уолтера: JavaScript Madness: Keyboard Events, или же можно нажать на нужную клавишу на тестовом стенде и получить код.

Когда-то в этих кодах была масса кросс-браузерных несовместимостей. Сейчас всё проще – таблицы кодов в различных браузерах почти полностью совпадают. Но некоторые несовместимости, всё же, остались. Вы можете увидеть их в таблице ниже. Слева – клавиша с символом, а справа – скан-коды в различных браузерах.

Таблица несовместимостей:

КлавишаFirefoxОстальные браузеры
;59186
=107187
-109188

Остальные коды одинаковы, код для нужного символа будет в тестовом стенде.

Тестовый стенд

<style>
#kinput { font-size: 150%; box-sizing: border-box; width: 95%; }
#area { width: 95%; box-sizing: border-box; height: 250px;
        border: 1px solid black; display: block; }
</style>
<form id="form" onsubmit="return false">
<p>Игнорировать:
<input type="checkbox" name="keydownIgnore" value="1"> keydown    
<input type="checkbox" name="keypressIgnore" value="1"> keypress    
<input type="checkbox" name="keyupIgnore" value="1"> keyup</p>
<p>Сфокусируйтесь на поле и нажмите какую-нибудь клавишу.</p>
<input type="text" placeholder="Клавиши нажимать тут" id="kinput" />
<textarea id="area"  readonly></textarea>
<input type="button" value="Очистить" onclick="area.value = ''" />
</form>
<script>
var kinput = document.getElementById('kinput');
var area = document.getElementById('area');
kinput.onkeydown = kinput.onkeyup = kinput.onkeypress = handle;

var lastTime = Date.now();

function handle(e) {
  if (form.elements[e.type + 'Ignore'].checked) return;
  var text = e.type +
    ' keyCode=' + e.keyCode +
    ' which=' + e.which +
    ' charCode=' + e.charCode +
    ' char=' + String.fromCharCode(e.keyCode || e.charCode) +
    (e.location!=null ? ' location=' + e.location : '') + 
    (e.key!=null ? ' key=' + e.key : '') + 
    (e.code!=null ? ' code=' + e.code : '') + 
    (e.locale!=null ? ' locale=' + e.locale : '') + 
    (e.shiftKey ? ' +shift' : '') +
    (e.ctrlKey ? ' +ctrl' : '') +
    (e.altKey ? ' +alt' : '') +
    (e.metaKey ? ' +meta' : '') + "\n";

  if (area.value && Date.now() - lastTime > 250) 
    { area.value += new Array(81).join('-') + '\n'; }
  lastTime = Date.now();

  area.value += text;  
  area.scrollTop = area.scrollHeight;
}
</script>

Событие keypress

Событие keypress возникает сразу после keydown, если нажата символьная клавиша, т.е. нажатие приводит к появлению символа.

Любые буквы, цифры генерируют keypress. Управляющие клавиши, такие как Ctrl, Shift, F1, F2… – keypress не генерируют.

Событие keypress позволяет получить код символа. В отличие от скан-кода, он специфичен именно для символа и различен для "z" и "я".

Код символа хранится в свойствах: charCode и which. Здесь скрывается целое «гнездо» кросс-браузерных несовместимостей, разбираться с которыми нет никакого смысла – запомнить сложно, а на практике нужна лишь одна «правильная» функция, позволяющая получить код везде.

Получение символа в keypress

Кросс-браузерная функция для получения символа из события keypress:

// event.type должен быть keypress
function getChar(event) {
  if (event.which == null) { // IE
    if (event.keyCode < 32) return null; // спец. символ
    return String.fromCharCode(event.keyCode)
  }

  if (event.which != 0 && event.charCode != 0) { // все кроме IE
    if (event.which < 32) return null; // спец. символ
    return String.fromCharCode(event.which); // остальные
  }

  return null; // спец. символ
}

Для общей информации – вот основные браузерные особенности, учтённые в getChar(event):

  1. Во всех браузерах, кроме IE, у события keypress есть свойство charCode, которое содержит код символа.
  2. Браузер IE для keypress не устанавливает charCode, а вместо этого он записывает код символа в keyCodekeydown/keyup там хранится скан-код).
  3. Также в функции выше используется проверка if(event.which!=0), а не более короткая if(event.which). Это не случайно! При event.which=null первое сравнение даст true, а второе – false.

В действии:

<input onkeypress="this.nextSibling.innerHTML = getChar(event)+''" /> <b></b>

Модификаторы shift, alt, ctrl и meta

Во всех событиях объекты KeyboardEvent присутствует информация о нажатых клавишах-модификаторах.

Синтаксис

event.altKey
event.ctrlKey
event.metaKey   // для Mac
event.shiftKey

Возвращаемое значение

Свойство возвращает true, если нажата соответствующая клавиша, и false - в противном случае

Комментарии

Чтобы пользователи операционных систем работали с комфортом, в паре с ctrlKey нужно обязательно использовать metaKey.

В JS-коде это означает, что для удобства пользователей Mac нужно проверять
if (event.ctrlKey || event.metaKey)

charCode

Свойство charCode содержит код Юникода сгенерированного печатного символа для события keypress

Синтаксис

event.charCode

Возвращаемое значение

Комментарии

Свойство не используется событиями «keydown» и «keyup».

Преобразовать код символа в Юникоде в строку можно с помощью метода String.fromCharCode().

Для событий keypress то же самое значение большинство броузеров записывают в свойство keyCode. Однако в Firefox свойство keyCode не определено для события keypress, поэтому следует использовать свойство charCode.

Данное свойство является нестандартным, отсутствует в модели событий IE8- и не имитируется в модели событий jQuery.

Для кроссбраузерного решения можно использовать следующий код:

var x = event.charCode || event.keyCode;

code

Свойство key возвращает строку, представлающее физическое расположение нажатой клавиши на клавиатуре.

Синтаксис

event.code

Комментарии

Свойство code представляет значение, которое не зависит ни от раскладки клавиатуры, ни от нажатия клавиш-модификаторов. Нажатию одной клавиши может соответствовать несколько различных символов, поэтому полученное значение не получится использовать для представления в виде текста.

Совместимость с браузерами

48,0Нет32,010,1Да

key

Свойство key возвращает строку, представлающее значение клавиши, на которой возникло событие.

Синтаксис

event.key

Возвращаемое значение

Для событий клавиатуры, генерирующих символы, это свойство получает значение нажатой клавиши (такое как "a" , "W" , "4" , "+", "$", ...).

Для событий клавиатуры, не генерирующих символы, это свойство содержит имя нажатой клавиши (такое как, "Tab", "Down", ...).

Совместимость с браузерами

51,09,023,0Да38

keyCode

Свойство keyCode возвращает виртуальный код нажатой клавиши.

Синтаксис

event.keyCode

Возвращаемое значение

Комментарии

В Firefox, свойство keyCode не работает на событие keypress (возаращает 0). Для кроссбраузерного решения можно использовать следующий код:

var x = event.charCode || event.keyCode;

Свойство keyCode не было стандартизовано, но определяется всеми броузерами, включая IE.

locale

Свойство locale определяет язык для событий клавиатуры и событий textinput.

Синтаксис

event.locale

Возвращаемое значение

Код языка (например, «en-GB»), идентифицирующий выбранную раскладку клавиатуры,если эта информация доступна.

Комментарии

Свойство locale поддерживается не всеми браузерами,

location

Свойство location определяет местоположение нажатой клавиши для событий клавиатуры.

Синтаксис

event.location

Возвращаемое значение

Возвращает число (константу), представляющее расположение клавиши на клавиатуре или другом устройстве ввода:
0. DOM_KEY_LOCATION_STANDARD
Кнопка не нажата на правой или левой стороне клавиатуры, а также не была нажата на цифровой клавиатуре (это значение представляет почти все клавиши на клавиатуре, например , "A" , "U" , "SPACE" или «5» )
1. DOM_KEY_LOCATION_LEFT
Левая клавиша была нажата (например , левый "CTRL" или "ALT")
2. DOM_KEY_LOCATION_RIGHT
Правая клавиша была нажата (например, правый "CTRL")
3. DOM_KEY_LOCATION_NUMPAD
Клавиша была нажата на цифровой клавиатуре (например, "2" клавишу на правой стороне на стандартной клавиатуре)
4. DOM_KEY_LOCATION_MOBILE
Клавиша была нажата на мобильном устройстве; это может быть либо физическая клавиатура, либо виртуальная клавиатура.
5. DOM_KEY_LOCATION_JOYSTICK
Клавиша была нажата на игровом контроллере или джойстике на мобильном устройстве.

Совместимость с браузерами

Да9,015,06,1Да

which

Свойство which возвращает виртуальный код нажатой клавиши.

Синтаксис

event.which

Возвращаемое значение

Комментарии

Свойство which в IE8-. Для этих версий браузера можно использовать свойство keyCode. Однако свойство keyCode не работает для события keypress в Firefox. Для кроссбраузерного решения можно использовать следующий код:

var x = event.which || event.keyCode;

Свойство which не стандартизовано и поэтому НЕ РЕКОМЕНДУЕТСЯ использовать.

Совместимость с браузерами

Да9,015,05,110,10