Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

keyboardshortcut.js 8.6KB

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