Работая в приложениях, очень много внимания мы уделяем клавиатуре. Если вдруг вам интересно, как выглядит это устройство, то на рис. 34.1 показан один из экземпляров, вероятно, столетней давности.
Рис. 34.1. Так выглядит музейный экспонат клавиатуры
Как бы то ни было, наши компьютеры (а именно выполняемые на них приложения) умеют взаимодействовать с этими усыпанными клавишами пластиковыми досками. Вас же этот процесс интересует редко. Однако в нашем случае в зависимости от выполняемой задачи думать об этом взаимодействии придется регулярно. Если быть точнее, то придется не только думать о нем, но и научиться его налаживать. Поэтому лучше отмените все ближайшие планы, так как текущая глава будет насыщенной.
К моменту ее завершения вы узнаете все о том, как прослушивать события клавиатуры, что каждое из них делает, и познакомитесь с рядом примеров, демонстрирующих удобные трюки, которые порой могут очень пригодиться.
Поехали!
Знакомьтесь с событиями клавиатуры
Для работы с клавиатурой в HTML-документе вам потребуется познакомиться с тремя событиями, а именно:
• keydown;
• keypress;
• keyup.
Глядя на названия этих событий, вы наверняка уже догадались, за что они отвечают. keydown срабатывает при нажатии клавиши, а keyup — при ее отпускании. Оба этих события работают для любой клавиши, с которой вы взаимодействуете.
Событие же keypress — это отдельный случай. На первый взгляд может показаться, что оно срабатывает при нажатии клавиши. Но, несмотря на название, срабатывает оно, только когда вы нажимаете на клавишу, которая отображает знак (букву, цифру и т. п.). Это может показаться не совсем понятным, но своеобразный смысл здесь все-таки присутствует.
Если вы нажмете и отпустите клавишу знака вроде буквы y, то увидите, что по порядку сработали события keydown, keypress и keyup. В данном случае keydown и keyup сработали потому, что клавиша y для них — просто клавиша. Событие же keypress сработало, так как клавиша y — это клавиша знака. Если вы нажмете и отпустите клавишу, которая на экране ничего не отображает (например, пробел, стрелка или функциональные клавиши), то увидите, что сработали только события keydown и keyup.
Это неявное отличие, но оно очень важно, чтобы нажатия клавиш были услышаны приложением.
Что сказал?
Странно, что событие под названием keypress не срабатывает при нажатии любой клавиши. Может быть, это событие следует назвать как-то иначе, например characterkeypress, но это, скорее всего, проблема МУ (все равно, что мнение коровы и ее мнение никого не волнует). (Подробнее о проблеме МУ здесь: http://bit.ly/kirupaMoo)
Использование событий
Прослушивание событий keydown, keyup и keypress аналогично любым другим событиям, которые мы прослушиваем и на которые реагируем. Вы вызываете addEventListener для элемента, который будет работать с этим событием, указываете событие, которое нужно прослушать, указываете функцию обработчика событий, которая вызывается, когда событие услышано, а также указываете значение trueилиfalse, определяя, должно ли оно прослушиваться в фазе всплытия.
Вот пример прослушивания трех событий клавиатуры в объекте window:
window.addEventListener("keydown", dealWithKeyboard, false);
window.addEventListener("keypress", dealWithKeyboard, false);
window.addEventListener("keyup", dealWithKeyboard, false);
function dealWithKeyboard(e) {
// вызывается, когда услышано любое из событий клавиатуры
}
Как только любое из этих событий будет услышано, последует вызов обработчика событий dealWithKeyboard. На деле же при нажатии клавиши знака этот обработчик будет вызван трижды. Все это вполне понятно, поэтому давайте увеличим уровень сложности и в последующих разделах уже выйдем за рамки основ.
Свойства события Keyboard
Когда происходит вызов обработчика событий, передается аргумент события Keyboard. Давайте вернемся к обработчику событий dealWithKeaboard из предыдущего раздела. В нем событие клавиатуры представлено передаваемым аргументом e:
function dealWithKeyboard(e) {
// вызывается, когда услышано любое событие клавиатуры
}
Этот аргумент содержит несколько свойств:
• KeyCode. Каждая клавиша клавиатуры имеет связанное с ней число. Это число возвращается свойством только для чтения.
• CharCode. Это свойство существует только в аргументах события, возвращенных событием keypress, и содержит код ASCII для любой нажатой клавиши знака.
• ctrlKey, altKey, shiftKey. Эти три свойства возвращают true, если нажата клавиша Ctrl, Alt или Shift.
• MetaKey. Это свойство похоже на ctrlKey, altKey и shiftKey тем, что возвращает true, если нажата клавиша Meta на клавиатурах Windows или клавиша Command на клавиатурах Apple.
Событие Keyboard содержит и другие свойства, но приведенные выше являются наиболее интересными. Используя их, вы можете проверять, какая была нажата клавиша, и реагировать соответственно. В двух последующих разделах вы увидите примеры.
ВНИМАНИЕ
Свойства charCode и keyCode считаются специалистами по веб-стандартам W3C устаревшими. Их альтернативой может стать мало поддерживаемое свойство code. Просто имейте это в виду и будьте готовы к обновлению кода, как только на трон взойдет преемник этих свойств.
Примеры
Теперь, когда скучные основы работы с событиями клавиатуры позади, пора рассмотреть некоторые примеры, которые прояснят (а может, и запутают) все пройденное.
Проверка нажатия конкретной клавиши
Следующий пример показывает, как использовать свойство keyCode для проверки нажатия конкретной клавиши:
window.addEventListener("keydown", checkKeyPressed, false);
function checkKeyPressed(e) {
if (e.keyCode == 65) {
console.log("The 'a' key is pressed.");
}
}
Здесь я проверяю клавишу a. Внутренне эта клавиша отображается значением 65 свойства keyCode. В случае если вы так и не зазубрили их в школе, можете обратиться к подручному списку кодов для всех клавиш и знаков по следующей ссылке: http://bit.ly/kirupaKeyCode.
Пожалуйста, не заучивайте все коды из этого списка, так как есть гораздо более интересные вещи для запоминания.
Прошу отметить следующее. Значения charCode и keyСode для конкретной клавиши не будут одинаковы. Помимо этого, charCode возвращается, только если обработчик событий сработал в ответ на keypress. В нашем примере событие keydown не содержало бы ничего полезного для свойства charCode.
Если вы захотите проверить charCode и использовать событие keypress, то предыдущий пример будет выглядеть так:
window.addEventListener("keypress", checkKeyPressed, false);
function checkKeyPressed(e) {
if (e.charCode == 97) {
console.log("The 'a' key is pressed.");
}
}
charCode для клавиши a — это 97. Опять же напомню, подробности можно взять из таблицы, приведенной по ссылке выше.
Совершение действий при нажатии клавиш стрелок
Чаще всего мы встречаемся с этим в играх, где нажатие стрелок приводит к выполнению действий. В следующем листинге показана реализация:
window.addEventListener("keydown", moveSomething, false);
function moveSomething(e) {
switch (e.keyCode) {
case 37:
// нажатие влево
break;
case 38:
// нажатие вверх
break;
case 39:
// нажатие вправо
break;
case 40:
// нажатие вниз
break;
}
}
Здесь все вполне понятно. Помимо прочего, это актуальный пример использования инструкции switch, которую вы изучили еще в далекой главе 4.
Определение нажатия нескольких клавиш
А вот теперь эпичная часть! Самое интересное связано с определением нажатия нескольких клавиш и соответственного реагирования. Далее показано, как это можно сделать:
window.addEventListener("keydown", keysPressed, false);
window.addEventListener("keyup", keysReleased, false);
let keys = [];
function keysPressed(e) {
// сохраняет запись о каждой нажатой клавише
keys[e.keyCode] = true;
// Ctrl + Shift + 5
if (keys[17] && keys[16] && keys[53]) {
// делает что-нибудь
}
// Ctrl + f
if (keys[17] && keys[70]) {
// делает что-нибудь
// предотвращает встроенное поведение браузера
e. preventDefault();
}
}
function keysReleased(e) {
// отмечает отпущенные клавиши
keys[e.keyCode] = false;
}
Чтобы разобрать все, что здесь происходит, понадобится отдельная глава, поэтому давайте пробежимся по верхам.
Во-первых, имеется массив клавиш, хранящий каждую клавишу, которую вы нажимаете:
let keys = [];
По мере нажатия клавиш происходит вызов обработчика событий keysPressed:
function keysPressed(e) {
// хранит запись о каждой нажатой клавише
keys[e.keyCode] = true;
// Ctrl + Shift + 5
if (keys[17] && keys[16] && keys[53]) {
// делает что-нибудь
}
// Ctrl + f
if (keys[17] && keys[70]) {
// делает что-нибудь
// предотвращает встроенное поведение браузера
e. preventDefault();
}
}
Когда клавиша отпускается, происходит вызов обработчика событий keysRealesed:
function keysReleased(e) {
// помечает отпущенные клавиши
keys[e.keyCode] = false;
}
Обратите внимание, как эти два обработчика событий взаимодействуют. При нажатии клавиш для них создается запись в массиве keys со значением true. При отпускании же клавиш их значения меняются на false. Существование в массиве нажимаемых вами клавиш поверхностно, важны лишь хранимые ими значения.
До тех пор пока ничего вроде всплывающего окна уведомления не мешает правильному вызову ваших обработчиков событий, с позиции массива keys будет возникать взаимно однозначное соответствие между нажатыми и отпущенными клавишами. Учитывая это, проверка определения комбинации нажатых клавиш производится в обработчике событий keysPressed. Выделенные в следующем коде строки показывают, как это работает:
function keysPressed(e) {
// хранит запись о каждой нажатой клавише
keys[e.keyCode] = true;
// Ctrl + Shift + 5
if (keys[17] && keys[16] && keys[53]) {
// делает что-то
}
// Ctrl + f
if (keys[17] && keys[70]) {
// делает что-то
// предотвращает стандартное поведение браузера
e. preventDefault();
}
}
Важно учитывать одну деталь: некоторые комбинации клавиш приводят к реагированию браузера. Чтобы избежать выполнения браузером ненужных вам действий, используйте метод preventDefault, как это выделено, при проверке использования Ctrl + F:
function keysPressed(e) {
// хранит запись о каждой нажатой клавише
keys[e.keyCode] = true;
// Ctrl + Shift + 5
if (keys[17] && keys[16] && keys[53]) {
// делает что-то
}
// Ctrl + f
if (keys[17] && keys[70]) {
// делает что-то
// предотвращает стандартное поведение браузера
e. preventDefault();
}
}
Метод preventDefault предотвращает стандартную реакцию браузера на событие. В данном случае он не дает браузеру показать диалоговое окно поиска. Различные комбинации клавиш будут запускать различные реакции браузера, поэтому держите этот метод на вооружении, чтобы исключить их.
В любом случае, при рассмотрении кода в совокупности у вас есть схема для удобной проверки нажатия нескольких клавиш.
КОРОТКО О ГЛАВНОМ
Клавиатура выступает важным элементом взаимодействия пользователей с компьютерами и аналогичными им устройствами. Несмотря на это, не всегда приходится иметь с ней дело напрямую. Ваш браузер, различные относящиеся к тексту элементы управления и аналогичные им компоненты уже справляются с этим по умолчанию. Тем не менее есть определенные приложения, где может потребоваться непосредственно поработать с клавиатурой. Этому и была посвящена текущая глава.
Она началась максимально скучно с объяснения принципа работы событий Keyboard и их аргументов событий. По мере продвижения все становилось интереснее: вы увидели некоторые примеры кода, где были показаны действия с клавиатурой. Если у вас есть какие-либо вопросы по этой или другой теме, не стесняйтесь обращаться с ними на форум https://forum.kirupa.com.