From 9a4cee1818eaa0f3c0b23419228049e686b84667 Mon Sep 17 00:00:00 2001 From: Etienne CHAMPETIER Date: Wed, 13 Jul 2016 14:22:57 +0200 Subject: [PATCH] Improve keyboard shortcut handling Use KeyboardEvent.key if available, match both lower and upper case letters to keep previous behaviour KeyboardEvent is a mess. KeyboardEvent.which gives you, in theory, a decimal representation of the key pressed. "r" or "R" gives you 82, which is "R", you can look at KeyboardEvent.shiftKey, but you don't have access to capslock... Maybe you want to use numbers, but of course NumPad will not give you the same than "normal" numbers ... Now if you use something else than letter, for exemple "?", on a QWERTY keyboard "/" and "?" gives you 191, on a AZERTY keyboard "," and "?" gives you 188, so we have to stick to letters. This was for keydown and keyup events, keypressed event return the real char (lower "a", "/", "?", ...) but it fails in some cases The only non broken property is KeyboardEvent.key, but it's only supported since Chrome 51, Opera 38, and not supported by Safari https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key A good reference & test: http://unixpapa.com/js/testkey.html http://unixpapa.com/js/key.html Signed-off-by: Etienne CHAMPETIER --- modules/keyboardshortcut/keyboardshortcut.js | 80 +++++++++++++------- 1 file changed, 52 insertions(+), 28 deletions(-) diff --git a/modules/keyboardshortcut/keyboardshortcut.js b/modules/keyboardshortcut/keyboardshortcut.js index 71f896e816..2677d3065d 100644 --- a/modules/keyboardshortcut/keyboardshortcut.js +++ b/modules/keyboardshortcut/keyboardshortcut.js @@ -3,67 +3,64 @@ var shortcuts = {}; function initShortcutHandlers() { shortcuts = { - 27: { + "ESCAPE": { character: "Esc", function: function() { APP.UI.showKeyboardShortcutsPanel(false); } }, - 67: { + "C": { character: "C", id: "toggleChatPopover", function: function() { APP.UI.toggleChat(); } }, - 68: { + "D": { character: "D", id: "toggleDesktopSharingPopover", function: function () { APP.conference.toggleScreenSharing(); } }, - 70: { + "F": { character: "F", id: "filmstripPopover", function: function() { APP.UI.toggleFilmStrip(); } }, - 77: { + "M": { character: "M", id: "mutePopover", function: function() { APP.conference.toggleAudioMuted(); } }, - 82: { + "R": { character: "R", function: function() { APP.conference.maybeToggleRaisedHand(); } }, - 84: { + "T": { character: "T", function: function() { APP.conference.muteAudio(true); } }, - 86: { + "V": { character: "V", id: "toggleVideoPopover", function: function() { APP.conference.toggleVideoMuted(); } }, - 191: { - character: "/", + "?": { + character: "?", function: function(e) { - // Only trigger on "?", not on "/". - if (e.shiftKey) { - APP.UI.toggleKeyboardShortcutsPanel(); - } + APP.UI.toggleKeyboardShortcutsPanel(); } } }; @@ -72,20 +69,21 @@ function initShortcutHandlers() { var KeyboardShortcut = { init: function () { initShortcutHandlers(); + var self = this; window.onkeyup = function(e) { - var keycode = e.which; + var key = self.getKeyboardKey(e).toUpperCase(); + var num = parseInt(key, 10); if(!($(":focus").is("input[type=text]") || $(":focus").is("input[type=password]") || $(":focus").is("textarea"))) { - if (typeof shortcuts[keycode] === "object") { - shortcuts[keycode].function(e); + if (shortcuts.hasOwnProperty(key)) { + shortcuts[key].function(e); } - else if (keycode >= "0".charCodeAt(0) && - keycode <= "9".charCodeAt(0)) { - APP.UI.clickOnVideo(keycode - "0".charCodeAt(0) + 1); + else if (!isNaN(num) && num >= 0 && num <= 9) { + APP.UI.clickOnVideo(num + 1); } - //esc while the smileys are visible hides them - } else if (keycode === 27 && + //esc while the smileys are visible hides them + } else if (key === "ESCAPE" && $('#smileysContainer').is(':visible')) { APP.UI.toggleSmileys(); } @@ -95,13 +93,13 @@ var KeyboardShortcut = { if(!($(":focus").is("input[type=text]") || $(":focus").is("input[type=password]") || $(":focus").is("textarea"))) { - if(e.which === "T".charCodeAt(0)) { + var key = self.getKeyboardKey(e).toUpperCase(); + if(key === "T") { if(APP.conference.isLocalAudioMuted()) APP.conference.muteAudio(false); } } }; - var self = this; $('body').popover({ selector: '[data-toggle=popover]', trigger: 'click hover', content: function() { @@ -116,14 +114,40 @@ var KeyboardShortcut = { * @returns {string} the keyboard shortcut used for the id given */ getShortcut: function (id) { - for (var keycode in shortcuts) { - if (shortcuts.hasOwnProperty(keycode)) { - if (shortcuts[keycode].id === id) { - return " (" + shortcuts[keycode].character + ")"; + for (var key in shortcuts) { + if (shortcuts.hasOwnProperty(key)) { + if (shortcuts[key].id === id) { + return " (" + shortcuts[key].character + ")"; } } } return ""; + }, + /** + * @param e a KeyboardEvent + * @returns {string} e.key or something close if not supported + */ + getKeyboardKey: function (e) { + if (typeof e.key === "string") { + return e.key; + } + if (e.type === "keypress" && ( + (e.which >= 32 && e.which <= 126) || + (e.which >= 160 && e.which <= 255) )) { + return String.fromCharCode(e.which); + } + // try to fallback (0-9A-Za-z and QWERTY keyboard) + switch (e.which) { + case 27: + return "Escape"; + case 191: + return e.shiftKey ? "?" : "/"; + } + if (e.shiftKey || e.type === "keypress") { + return String.fromCharCode(e.which); + } else { + return String.fromCharCode(e.which).toLowerCase(); + } } };