You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

keyboardshortcut.js 7.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /* global APP, $, JitsiMeetJS */
  2. /**
  3. * Initialise global shortcuts.
  4. * Global shortcuts are shortcuts for features that don't have a button or
  5. * link associated with the action. In other words they represent actions
  6. * triggered _only_ with a shortcut.
  7. */
  8. function initGlobalShortcuts() {
  9. KeyboardShortcut.registerShortcut("ESCAPE", null, function() {
  10. APP.UI.showKeyboardShortcutsPanel(false);
  11. });
  12. KeyboardShortcut.registerShortcut("?", null, function() {
  13. JitsiMeetJS.analytics.sendEvent("shortcut.shortcut.help");
  14. APP.UI.toggleKeyboardShortcutsPanel();
  15. }, "keyboardShortcuts.toggleShortcuts");
  16. KeyboardShortcut.registerShortcut("R", null, function() {
  17. JitsiMeetJS.analytics.sendEvent("shortcut.raisedhand.toggled");
  18. APP.conference.maybeToggleRaisedHand();
  19. }, "keyboardShortcuts.raiseHand");
  20. KeyboardShortcut.registerShortcut("T", null, function() {
  21. JitsiMeetJS.analytics.sendEvent("shortcut.talk.clicked");
  22. APP.conference.muteAudio(true);
  23. }, "keyboardShortcuts.pushToTalk");
  24. /**
  25. * FIXME: Currently focus keys are directly implemented below in onkeyup.
  26. * They should be moved to the SmallVideo instead.
  27. */
  28. KeyboardShortcut._addShortcutToHelp("0", "keyboardShortcuts.focusLocal");
  29. KeyboardShortcut._addShortcutToHelp("1-9", "keyboardShortcuts.focusRemote");
  30. }
  31. /**
  32. * Map of shortcuts. When a shortcut is registered it enters the mapping.
  33. * @type {{}}
  34. */
  35. let _shortcuts = {};
  36. /**
  37. * Maps keycode to character, id of popover for given function and function.
  38. */
  39. var KeyboardShortcut = {
  40. init: function () {
  41. initGlobalShortcuts();
  42. var self = this;
  43. window.onkeyup = function(e) {
  44. var key = self._getKeyboardKey(e).toUpperCase();
  45. var num = parseInt(key, 10);
  46. if(!($(":focus").is("input[type=text]") ||
  47. $(":focus").is("input[type=password]") ||
  48. $(":focus").is("textarea"))) {
  49. if (_shortcuts.hasOwnProperty(key)) {
  50. _shortcuts[key].function(e);
  51. }
  52. else if (!isNaN(num) && num >= 0 && num <= 9) {
  53. APP.UI.clickOnVideo(num + 1);
  54. }
  55. //esc while the smileys are visible hides them
  56. } else if (key === "ESCAPE" &&
  57. $('#smileysContainer').is(':visible')) {
  58. APP.UI.toggleSmileys();
  59. }
  60. };
  61. window.onkeydown = function(e) {
  62. if(!($(":focus").is("input[type=text]") ||
  63. $(":focus").is("input[type=password]") ||
  64. $(":focus").is("textarea"))) {
  65. var key = self._getKeyboardKey(e).toUpperCase();
  66. if(key === "T") {
  67. if(APP.conference.isLocalAudioMuted())
  68. APP.conference.muteAudio(false);
  69. }
  70. }
  71. };
  72. $('body').popover({ selector: '[data-toggle=popover]',
  73. trigger: 'click hover',
  74. content: function() {
  75. return this.getAttribute("content")
  76. + self._getShortcutTooltip(this.getAttribute("shortcut"));
  77. }
  78. });
  79. },
  80. /**
  81. * Registers a new shortcut.
  82. *
  83. * @param shortcutChar the shortcut character triggering the action
  84. * @param shortcutAttr the "shortcut" html element attribute mappring an
  85. * element to this shortcut and used to show the shortcut character on the
  86. * element tooltip
  87. * @param exec the function to be executed when the shortcut is pressed
  88. * @param helpDescription the description of the shortcut that would appear
  89. * in the help menu
  90. */
  91. registerShortcut: function( shortcutChar,
  92. shortcutAttr,
  93. exec,
  94. helpDescription) {
  95. _shortcuts[shortcutChar] = {
  96. character: shortcutChar,
  97. shortcutAttr: shortcutAttr,
  98. function: exec
  99. };
  100. if (helpDescription)
  101. this._addShortcutToHelp(shortcutChar, helpDescription);
  102. },
  103. /**
  104. * Unregisters a shortcut.
  105. *
  106. * @param shortcutChar unregisters the given shortcut, which means it will
  107. * no longer be usable
  108. */
  109. unregisterShortcut: function(shortcutChar) {
  110. _shortcuts.remove(shortcutChar);
  111. this._removeShortcutFromHelp(shortcutChar);
  112. },
  113. /**
  114. * Returns the tooltip string for the given shortcut attribute.
  115. *
  116. * @param shortcutAttr indicates the popover associated with the shortcut
  117. * @returns {string} the tooltip string to add to the given shortcut popover
  118. * or an empty string if the shortcutAttr is null, an empty string or not
  119. * found in the shortcut mapping
  120. */
  121. _getShortcutTooltip: function (shortcutAttr) {
  122. if (typeof shortcutAttr === "string" && shortcutAttr.length > 0) {
  123. for (var key in _shortcuts) {
  124. if (_shortcuts.hasOwnProperty(key)
  125. && _shortcuts[key].shortcutAttr
  126. && _shortcuts[key].shortcutAttr === shortcutAttr) {
  127. return " (" + _shortcuts[key].character + ")";
  128. }
  129. }
  130. }
  131. return "";
  132. },
  133. /**
  134. * @param e a KeyboardEvent
  135. * @returns {string} e.key or something close if not supported
  136. */
  137. _getKeyboardKey: function (e) {
  138. if (typeof e.key === "string") {
  139. return e.key;
  140. }
  141. if (e.type === "keypress" && (
  142. (e.which >= 32 && e.which <= 126) ||
  143. (e.which >= 160 && e.which <= 255) )) {
  144. return String.fromCharCode(e.which);
  145. }
  146. // try to fallback (0-9A-Za-z and QWERTY keyboard)
  147. switch (e.which) {
  148. case 27:
  149. return "Escape";
  150. case 191:
  151. return e.shiftKey ? "?" : "/";
  152. }
  153. if (e.shiftKey || e.type === "keypress") {
  154. return String.fromCharCode(e.which);
  155. } else {
  156. return String.fromCharCode(e.which).toLowerCase();
  157. }
  158. },
  159. /**
  160. * Adds the given shortcut to the help dialog.
  161. *
  162. * @param shortcutChar the shortcut character
  163. * @param shortcutDescriptionKey the description of the shortcut
  164. * @private
  165. */
  166. _addShortcutToHelp: function (shortcutChar, shortcutDescriptionKey) {
  167. var listElement = document.createElement("li");
  168. listElement.id = shortcutChar;
  169. var spanElement = document.createElement("span");
  170. spanElement.className = "item-action";
  171. var kbdElement = document.createElement("kbd");
  172. kbdElement.className = "regular-key";
  173. kbdElement.innerHTML = shortcutChar;
  174. spanElement.appendChild(kbdElement);
  175. var descriptionElement = document.createElement("span");
  176. descriptionElement.className = "item-description";
  177. descriptionElement.setAttribute("data-i18n", shortcutDescriptionKey);
  178. descriptionElement.innerHTML
  179. = APP.translation.translateString(shortcutDescriptionKey);
  180. listElement.appendChild(spanElement);
  181. listElement.appendChild(descriptionElement);
  182. var parentListElement
  183. = document.getElementById("keyboard-shortcuts-list");
  184. if (parentListElement)
  185. parentListElement.appendChild(listElement);
  186. },
  187. /**
  188. * Removes the list element corresponding to the given shortcut from the
  189. * help dialog
  190. * @private
  191. */
  192. _removeShortcutFromHelp: function (shortcutChar) {
  193. var parentListElement
  194. = document.getElementById("keyboard-shortcuts-list");
  195. var shortcutElement = document.getElementById(shortcutChar);
  196. if (shortcutElement)
  197. parentListElement.removeChild(shortcutElement);
  198. }
  199. };
  200. module.exports = KeyboardShortcut;