Обнаружение команды + нажатия клавиши в Safari

Я пытаюсь перехватить команду + нажатие клавиши в Safari. Я добавил обработчик событий следующим образом:

document.onkeypress = handleKeyPress;

function handleKeyPress(event) {
    if ("+" === String.fromCharCode(event.charCode) && event.metaKey) {
        // my code here
        return false;
    }
    return true;
}

Когда я нажимаю command shift = (shift = равно + на моей клавиатуре США ), оператор if не возвращает true.

Если я удалю часть event.metaKey оператора if и нажму shift =, оператор if вернет true.

Кроме того, если я изменю соответствующую строку с "+" на "=" и нажму command = (с клавишей Shift или без нее), оператор if вернет true.

Есть ли способ фактически обнаружить команду + нажатие клавиши (не предполагая, что клавиша + является сдвигом = и проверяя event.shiftKey, поскольку это не будет верно для некоторых клавиатур, отличных от США)?


person Ceri Morgan    schedule 31.08.2011    source источник


Ответы (3)


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

В любом случае: Ключевые события сложны, часто потому, что свойства keyCode/charCode/what не всегда совпадают с правильной буквой, поэтому String.fromCharCode не всегда даст вам правильную строку. keyIdentifier иногда лучше смотреть, но не всегда (например, его коды для буквенных клавиш всегда являются прописными буквами).

То, что я делал в прошлом (и я не уверен, что это лучший способ сделать это, но он работает нормально), вместо этого прослушивал события keydown и keyup, а также «складывал» ключи-модификаторы. т.е. всякий раз, когда клавиша нажата, проверьте, является ли она клавишей-модификатором (например, если это cmd, ctrl, alt или shift). Если он есть, добавьте его в «стек» модификаторов. Сделайте наоборот на keyup; если выпущенный ключ был модификатором, удалите его из стека.

Теперь, вернувшись в обработчик нажатия клавиши, если клавиша не была клавишей-модификатором, вы можете отправить событие нажатия клавиши (которое, в отличие от события нажатия клавиши, будет иметь довольно надежное свойство keyIdentifier для проверки) и стек модификаторов вместе с на какой-то другой обратный вызов, который возьмет его оттуда.

В вашем случае такой обратный вызов проверит, что cmd-key находится в стеке и что keyIdentifier для события keydown — «U + 002B» (это код Unicode для +).

Я собрал пример jsfiddle того, о чем говорю. Если вы щелкнете на панели «Результат» (чтобы убедиться, что она находится в фокусе) и нажмете ⌘+, она должна отобразить использованную вами комбинацию клавиш и написать «Успех!» ниже. В противном случае он просто покажет комбинацию клавиш. На моей клавиатуре знак «плюс» доступен напрямую, поэтому комбинация клавиш, которую я вижу, — это просто «⌘+». Но если вам нужно сдвинуть, чтобы ввести знак плюс, вы должны увидеть «⇧⌘+».

Это обобщенный фрагмент кода, который подходит для обработки сочетаний клавиш в Safari/Mac, так что вы можете использовать его, если хотите. Вы захотите добавить несколько прослушивателей событий, чтобы сбросить стек модификаторов для событий размытия и тому подобного. В идеале стек модификаторов сбрасывался бы автоматически, когда вы отпускаете клавиши, но поскольку что-то может привести к тому, что браузер или наблюдаемый элемент/окно/документ потеряют фокус, события нажатия клавиш не будут обрабатываться, а отпущенные клавиши останутся в выигрыше. не удаляться из стека. Поэтому проверьте события размытия.

person Flambino    schedule 31.08.2011
comment
Во-первых, я согласен на 100% с осторожностью при угоне ⌘+. У меня есть плагин, который переопределяет встроенные команды масштабирования и вызывает уровень масштабирования для каждого сайта, поэтому я думаю, что в данном случае это уместно. Во-вторых, спасибо за ответ. Я думаю, вы предоставили мне все инструменты, которые мне нужны, чтобы найти ответ, но я потрачу день, чтобы убедиться, что я могу взять эту информацию и сделать так, чтобы она соответствовала моим потребностям. - person Ceri Morgan; 01.09.2011
comment
Работает отлично... спасибо! Одно небольшое исправление к вашему примеру jsfiddle: у вас есть юникод для клавиши «=» (U + 003D) вместо клавиши «+» (U + 002B) в функции exampleCallback. - person Ceri Morgan; 01.09.2011
comment
@CeriMorgan: Ах, извините. Когда я собирал jsfiddle, я неправильно понял ваш вопрос, и хотя вы хотите слушать ⌘=, а не ⌘+. Я отредактировал свой ответ перед публикацией, но забыл отредактировать файл jsfiddle. В любом случае; здорово, что в остальном код работает - person Flambino; 01.09.2011

Зарегистрируйте объект события в объекте окна первого уровня, например, event = window.EE, затем просмотрите его с помощью Firebug или инструментов веб-разработчика Safari и просмотрите значения, которые запускаются, когда вы хотите. Так вы будете знать, с чем сравнивать.

person Community    schedule 31.08.2011
comment
Я сравнил весь объект события в обоих случаях (команда shift = и команда =), и результаты кажутся точно такими же, за исключением присутствия модификатора shiftKey в первом случае. Однако я не хочу делать предположение, что shift= всегда будет + (у меня уже есть один пользователь, для которого это неверно). - person Ceri Morgan; 31.08.2011

К сожалению, я не думаю, что есть ответ. Проблема в том, что для CMD+SHIFT+= нажимается charCode 61 (=), а не 43 (+). Похоже, это общесистемный дизайн, поскольку сама Mac OS X интерпретирует CMD+SHIFT+= как = плюс два модификатора, а не + и COMMAND.

Я собрал простой jsFiddle, чтобы показать это: http://jsfiddle.net/ScuDj/1/

По сути, вам придется иметь дело с раскладками клавиатуры, если вы хотите обнаружить COMMAND +.

В качестве альтернативы вы можете поддерживать только цифровую клавиатуру + — она работает стабильно! (просто шучу ;-)

(Также: я пытался подключиться к событию textInput, но не смог заставить его зарегистрироваться глобально. Я думаю, что это работает только на domNodes. На самом деле я мало использовал это событие.)

person OverZealous    schedule 31.08.2011