События клавиатуры: keyup, keydown, keypress

События клавиатуры: keyup, keydown, keypress

Здравствуйте!  В этой статье я хотел бы рассказать  о событиях  клавиатуры. Мы с  вами уже рассмотрели события мыши и вот теперь разберем события клавиатуры.

Здесь материала не так много,  как  с событиями мыши, но все же хватает. Основные события клавиатуры — это keydown и keypress.

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

События keydown и keyup

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

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

Скан-коды

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

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

Для других символов, в частности, знаков пунктуации, есть таблица кодов. Эту таблицу с легкостью можно найти в Интернете.

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

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

Клавиша Firefox Остальные браузеры
; 59 186
= 107 187
109 189

Событие keypress

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

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

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

Код символа сохраняется в  таких свойствах: charCode и which.

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

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

// event.type должен быть keypress
function getKey(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; // спец. символ
}

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

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

Как и у других событий, связанных с пользовательским вводом, поддерживаются свойства shiftKey, ctrlKey, altKey и metaKey.

Читайте также  Делегирование событий в JavaScript

Они установлены в true, если нажаты клавиши-модификаторы – соответственно, Shift, Ctrl, Alt и Cmd для Mac (подробнее об этом здесь)

Отмена пользовательского ввода

Появление символа можно предотвратить, если отменить действие браузера на keydown/keypress ( я писал про отмену  событий браузера по умолчанию)

При keydown/keypress значение ещё старое

На момент срабатывания keydown/keypress клавиша ещё не обработана браузером.

Поэтому в обработчике значение input.value – старое, т.е. до ввода. А что, если мы хотим обработать input.value именно после ввода? Самое простое решение – использовать событие keyup, либо запланировать обработчик через setTimeout(..,0).

Отмена любых действий

Отменять можно не только символ, но и  любое действие клавиш.

Например:

  • При отмене Backspace – символ не удалится.
  • При отмене PageDown – страница не прокрутится.
  • При отмене Tab – курсор не перейдёт на следующее поле.

Пример: перевод символа в верхний регистр

В примере ниже действие браузера отменяется с помощью  вызова return false, а вместо него в input добавляется значение в верхнем регистре:

<input id="only-upper" type="text" size="2">
<script>
  document.getElementById('only-upper').onkeypress = function(e) {
    // спец. сочетание - не обрабатываем
    if (e.ctrlKey || e.altKey || e.metaKey) return;

    var char = getChar(e);

    if (!char) return; // спец. символ - не обрабатываем

    this.value = char.toUpperCase();

    return false;
  };
</script>

Пример простой чат.

В этом примере разработан простейший чат.

  <html>
	<head>
		<title>
			chat js
		</title>
		<meta charset="utf-8">
		<style>
		 .msgbox {
		 	width:  80%;
		 }
		 .msgbox p {
		 	border: 2px solid red;
		 	border-radius:  10px;
		 	padding:  15px;
		 }
		</style>
	</head>
	<body>
		Введите сообщение: <input id="msg" type="text">
		<div class="msgbox">
		</div>
		<script>
             var msg = document.getElementById("msg");
             var msgbox = document.querySelector("div.msgbox");
             msg.addEventListener("keyup", function(bobik) {
                  if(bobik.keyCode == 13) {
                    var newline = document.createElement("p");
                    newline.appendChild(document.createTextNode(this.value));
                    msgbox.appendChild(newline);
                    this.value="";
                  }
             });

		</script>
	</body>
</html>

Просмотреть  пример

В примере обрабатывается нажатие клавиши Enter, которая имеет код 13 и если она нажата, то сообщение введенное в текстовый инпут, отображается на странице.

Читайте также  Мышь: Drag'n'Drop или перетаскивание элементов на веб-странице

Несовместимости

Некоторые несовместимости в порядке срабатывания клавиатурных событий (когда что) ещё существуют.

Стоит иметь в виду три основных категории клавиш, работа с которыми отличается.

Категория События Описание
Печатные клавиши S 1 , keydown
keypress
keyup
Нажатие вызывает keydown и keypress. Когда клавишу отпускают, срабатывает keyup.Исключение – CapsLock под MacOS, с ним есть проблемы:

  • В Safari/Chrome/Opera: при включении только keydown, при отключении только keyup.
  • В Firefox: при включении и отключении только keydown.
Специальные клавиши Alt Esc ⇧ keydown keyup Нажатие вызывает keydown. Когда клавишу отпускают, срабатывает keyup.Некоторые браузеры могут дополнительно генерировать и keypress, например IE для Esc.

На практике это не доставляет проблем, так как для специальных клавиш мы всегда используем keydown/keyup.

Сочетания с печатной клавишей Alt+E
Ctrl+У
Cmd+1
keydown
keypress?
keyup
Браузеры под Windows – не генерируют keypress, браузеры под MacOS – генерируют.

Кроме того, если сочетание вызвало браузерное действие или диалог («Сохранить файл», «Открыть» и т.п., ряд диалогов можно отменить при keydown), то может быть только keydown.

Общий вывод можно сделать такой:

  • Обычные символы работают везде корректно.
  • CapsLock под MacOS ведёт себя плохо, не стоит ставить на него обработчики вообще.
  • Для других специальных клавиш и сочетаний с ними следует использовать только keydown.

Итого

Итак подведем итоги:

  1. Для реализации горячих клавиш, включая сочетания – используйте keydown. Скан-код будет считан в keyCode, почти все скан-коды кросс-браузерны, кроме нескольких пунктуационных, перечисленных в таблице выше.
  2. Если нужен именно символ – используйте keypress. При этом функция getChar позволит получить символ и отфильтровать лишние срабатывания. Гарантированно получать символ можно только при нажатии обычных клавиш, если речь о сочетаниях с модификаторами, то keypress не всегда будет генерироваться.
  3. Ловля CapsLock глючит под MacOS. Её можно организовать при помощи проверки navigator.userAgent и navigator.platform, а лучше вообще не трогать эту клавишу.

Распространённая ошибка – использовать события клавиатуры для работы с полями ввода в формах.

Это нежелательно. События клавиатуры предназначены именно для работы с клавиатурой. Да, их можно использовать для проверки ввода в <input>, но будут недочёты. Например, текст может быть вставлен мышкой, при помощи правого клика и меню, без единого нажатия клавиши. И как нам  тут помогут события клавиатуры?

Некоторые мобильные устройства также не генерируют keypress/keydown, а сразу вставляют текст в поле. Обработать ввод на них при помощи клавиатурных событий нельзя.

Далее мы разберём события для элементов форм, которые позволяют работать с вводом в формы правильно.

Их можно использовать как отдельно от событий клавиатуры, так и вместе с ними.

Задачи

Поле только для цифр

Вам нужно сделать так чтобы в текстовое поле можно вводить было только цифры.

Отследить одновременное нажатие

Вам надо создать  функцию runOnKeys(func, code1, code2, … code_n), которая запускает func при одновременном нажатии клавиш со скан-кодами code1, code2, …, code_n.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Плюсануть
Поделиться

Об авторе

admin administrator

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: