Предисловие
Я не буду писать здесь об эволюции сети, о плавном переходе от сайтов к сервисам и веб-приложениям и ссылаться на прочие подобные умозаключения, с банальностью которых может поспорить разве что их справедливость.
Вместо этого я попытаюсь поделиться одной из своих наработок, искренне надеясь, что кому-нибудь эта информация действительно пригодится (хотя бы в плане общей идеи).
Ни для кого не секрет, что JS-фреймворки делают задачу «повесить хоткей на конкретную кнопку» если и не тривиальной, то достаточно простой. И даже задача максимально упростить и автоматизировать привязку «горячих клавиш» к функциональным элементам решается достаточно просто.
Прежде всего, расскажу об объективных сложностях и ограничениях использования «горячих клавиш».
Теория
«горячие клавиши» заняты браузером
Да, большинство удобых и привычных пользователю «горячих клавиш» занято браузером. И это-то еще полбеды, а беда в том, что заняты они в разных браузерах разные! К примеру, было бы чудесно использовать клавиши перемещения («стрелочки») с каким-либо модификатором для навигации, например, между страницами длинных списков. «С каким-либо» — это хорошо, а с каким? Alt-влево/Alt-вправо задействованы в FF и IE, Ctrl-влево/Ctrl-вправо — в опере, оба этих способа — в Safari для внутрибраузерной навигации назад/вперед, и даже если бы была техническая возможность заблокировать эту функциональность — это было бы очень и очень плохой идеей. Это лишь для примера, и практически все «удобные и привычные» «горячие клавиши» уже заняты — иначе, наверное, они бы не были ни привычными, ни (как следствие) удобными. Это факт накладывает существенные ограничения на использования на сайтах, и выбирать их следует чрезвычайно осторожно.«горячие клавиши» заняты чем-нибудь еще
Категорически то же самое справедливо и для «горячих клавиш», занятых, например, операционной системой. Например — в полях ввода те же самые Ctrl-влево/Ctrl-вправо означают нечто иное, но тоже удобное и привычное пользователю. Пример с пользователем, нажимающим Ctrl-влево в input/textarea и получающий в результате несколько не то, что он имел в виду, напрашивается сам собой.Модификаторы, вообще говоря, разные
Ctrl, Alt и Shift присутствуют на клавиатуре PC. Но кроме PC еще много чего есть… например, Mac. Чтобы корректно реализовать «горячие клавиши», необходимо хотя бы в общих чертах знать, какие модификаторы имеются на других платформах, где расположены и чем отличаются… а в идеале, конечно, неплохо бы иметь возможность увидеть-пощупать-потыкать так сказать физически, а не у всех такая возможность имеется.
Напоследок замечу, что это всё — всего лишь затруднения, а не какие-то непреодолимые препятствия.
Практика
Идея
Она проста: определяем символьные обозначения клавиш, приписываем к активным элементам дополнительный класс, имя которого совпадает с символьным обозначением клавиши, а при нажатии любой кнопки смотрим, нет ли на странице активного элемента с классом, имя которого совпадает с символьным обозначением нажатой кнопки. Если есть — активизируем найденный активный элемент.
Реализация
Первые две подзадачи с моей точки зрения тривиальны и не требуют подробного рассмотрения. Остановимся на третьей.
Ловим нажатие на кнопку (тривиально):
$(document).keydown(CheckKeyDown);
Далее стоит как-то централизованно решить задачу «не мешай пользователю комфортно вводить текст». Я долго искал (но так и не нашел), как определить какой элемент в данный момент имеет фокус (может, подскажет кто?) с целью отключать «горячие клавиши», если «фокусированный» элемент является полем ввода. В конце концов решил обойтись глобальной переменной, блокирующей «горячие клавиши»:
hotkeysDisabled = false;
$('input, textarea').focus(function(){hotkeysDisabled=true;}).blur(function(){hotkeysDisabled=false});
function CheckKeyDown(e) {
if(hotkeysDisabled)
return true;
...
Если кто-нибудь знает способ лучше и изящнее — буду благодарен за содержательный комментарий.
Настало время определить символьное обозначение нажатой клавиши. Вариант «оставить число как есть» был отвергнут сразу — использовать символьное обозначение вида ctrl_13 или, не к ночи будь помянуто, alt_219 крайне неудобно. Одним только использованием String.fromCharCode() тоже не обойтись — очень часто он выдает такое, что к классу не припишешь. Других штатных средств я не нашел, посему составил громоздкую и некрасивую конструкцию вот такого вида:
function keyCodeString(e)
{
var keyCodeStrings = {
8: 'backspace',
9: 'tab',
...
222: 'quote'
}
...
s = '';
if(e.ctrlKey) s = s + 'ctrl_';
if(e.altKey) s = s + 'alt_';
return s + keyCodeStrings[e.keyCode];
}
Несмотря на отсутствие изящности исполнения, у данной конструкции имеется неоспоримое преимущество — она адекватно работает. Во всяком случае, в лабораторных условиях.
Остался последний шаг — активировать найденное, если оно найдено. Достаточно очевидно, но все-таки опишу…
Переход по ссылке:
var keyCode = keyCodeString(e);
var selector='a.'+keyCode;
if($(selector).size() > 0)
{
location.href=$(selector).attr('href'); // your favorite load/go method
return false;
}
Активизация поля ввода/нажатие на кнопку:
$('.'+keyCode+':input').focus().click();
Вот, наверное, и все.
Послесловие
Код целиком можно посмотреть здесь.
Не претендую на полное раскрытие темы, приветствую различные коррективы, дополнения и конструктивную критику. К любой части топика применимо правило: «если вы знаете, как сделать лучше — пожалуйста, скажите мне об этом». Благодарю за внимание.