|
|
|
@ -1,91 +1,64 @@ |
|
|
|
|
/* global APP, $, JitsiMeetJS */ |
|
|
|
|
//maps keycode to character, id of popover for given function and function
|
|
|
|
|
var shortcuts = {}; |
|
|
|
|
function initShortcutHandlers() { |
|
|
|
|
shortcuts = { |
|
|
|
|
"ESCAPE": { |
|
|
|
|
character: "Esc", |
|
|
|
|
function: function() { |
|
|
|
|
APP.UI.showKeyboardShortcutsPanel(false); |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
"C": { |
|
|
|
|
character: "C", |
|
|
|
|
id: "toggleChatPopover", |
|
|
|
|
function: function() { |
|
|
|
|
JitsiMeetJS.analytics.sendEvent('shortcut.chat.toggled'); |
|
|
|
|
APP.UI.toggleChat(); |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
"D": { |
|
|
|
|
character: "D", |
|
|
|
|
id: "toggleDesktopSharingPopover", |
|
|
|
|
function: function () { |
|
|
|
|
JitsiMeetJS.analytics.sendEvent('shortcut.screen.toggled'); |
|
|
|
|
APP.conference.toggleScreenSharing(); |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
"F": { |
|
|
|
|
character: "F", |
|
|
|
|
id: "filmstripPopover", |
|
|
|
|
function: function() { |
|
|
|
|
JitsiMeetJS.analytics.sendEvent('shortcut.film.toggled'); |
|
|
|
|
APP.UI.toggleFilmStrip(); |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
"M": { |
|
|
|
|
character: "M", |
|
|
|
|
id: "mutePopover", |
|
|
|
|
function: function() { |
|
|
|
|
JitsiMeetJS.analytics.sendEvent('shortcut.audiomute.toggled'); |
|
|
|
|
APP.conference.toggleAudioMuted(); |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
"R": { |
|
|
|
|
character: "R", |
|
|
|
|
function: function() { |
|
|
|
|
JitsiMeetJS.analytics.sendEvent('shortcut.raisedhand.toggled'); |
|
|
|
|
APP.conference.maybeToggleRaisedHand(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
}, |
|
|
|
|
"T": { |
|
|
|
|
character: "T", |
|
|
|
|
function: function() { |
|
|
|
|
JitsiMeetJS.analytics.sendEvent('shortcut.talk.clicked'); |
|
|
|
|
APP.conference.muteAudio(true); |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
"V": { |
|
|
|
|
character: "V", |
|
|
|
|
id: "toggleVideoPopover", |
|
|
|
|
function: function() { |
|
|
|
|
JitsiMeetJS.analytics.sendEvent('shortcut.videomute.toggled'); |
|
|
|
|
APP.conference.toggleVideoMuted(); |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
"?": { |
|
|
|
|
character: "?", |
|
|
|
|
function: function(e) { |
|
|
|
|
JitsiMeetJS.analytics.sendEvent('shortcut.shortcut.help'); |
|
|
|
|
APP.UI.toggleKeyboardShortcutsPanel(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
/** |
|
|
|
|
* Initialise global shortcuts. |
|
|
|
|
* Global shortcuts are shortcuts for features that don't have a button or |
|
|
|
|
* link associated with the action. In other words they represent actions |
|
|
|
|
* triggered _only_ with a shortcut. |
|
|
|
|
*/ |
|
|
|
|
function initGlobalShortcuts() { |
|
|
|
|
|
|
|
|
|
KeyboardShortcut.registerShortcut("ESCAPE", null, function() { |
|
|
|
|
APP.UI.showKeyboardShortcutsPanel(false); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
KeyboardShortcut.registerShortcut("?", null, function() { |
|
|
|
|
JitsiMeetJS.analytics.sendEvent("shortcut.shortcut.help"); |
|
|
|
|
APP.UI.toggleKeyboardShortcutsPanel(); |
|
|
|
|
}, "keyboardShortcuts.toggleShortcuts"); |
|
|
|
|
|
|
|
|
|
KeyboardShortcut.registerShortcut("R", null, function() { |
|
|
|
|
JitsiMeetJS.analytics.sendEvent("shortcut.raisedhand.toggled"); |
|
|
|
|
APP.conference.maybeToggleRaisedHand(); |
|
|
|
|
}, "keyboardShortcuts.raiseHand"); |
|
|
|
|
|
|
|
|
|
KeyboardShortcut.registerShortcut("T", null, function() { |
|
|
|
|
JitsiMeetJS.analytics.sendEvent("shortcut.talk.clicked"); |
|
|
|
|
APP.conference.muteAudio(true); |
|
|
|
|
}, "keyboardShortcuts.pushToTalk"); |
|
|
|
|
|
|
|
|
|
KeyboardShortcut.registerShortcut("F", 'filmstripPopover', function() { |
|
|
|
|
JitsiMeetJS.analytics.sendEvent("shortcut.film.toggled"); |
|
|
|
|
APP.UI.toggleFilmStrip(); |
|
|
|
|
}, "keyboardShortcuts.toggleFilmstrip"); |
|
|
|
|
|
|
|
|
|
// Focus keys are directly implemented below.
|
|
|
|
|
KeyboardShortcut._addShortcutToHelp("0", "keyboardShortcuts.focusLocal"); |
|
|
|
|
KeyboardShortcut._addShortcutToHelp("1-9", "keyboardShortcuts.focusRemote"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Map of shortcuts. When a shortcut is registered it enters the mapping. |
|
|
|
|
* @type {{}} |
|
|
|
|
*/ |
|
|
|
|
let _shortcuts = {}; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Maps keycode to character, id of popover for given function and function. |
|
|
|
|
*/ |
|
|
|
|
var KeyboardShortcut = { |
|
|
|
|
init: function () { |
|
|
|
|
initShortcutHandlers(); |
|
|
|
|
initGlobalShortcuts(); |
|
|
|
|
|
|
|
|
|
var self = this; |
|
|
|
|
window.onkeyup = function(e) { |
|
|
|
|
var key = self.getKeyboardKey(e).toUpperCase(); |
|
|
|
|
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 (shortcuts.hasOwnProperty(key)) { |
|
|
|
|
shortcuts[key].function(e); |
|
|
|
|
if (_shortcuts.hasOwnProperty(key)) { |
|
|
|
|
_shortcuts[key].function(e); |
|
|
|
|
} |
|
|
|
|
else if (!isNaN(num) && num >= 0 && num <= 9) { |
|
|
|
|
APP.UI.clickOnVideo(num + 1); |
|
|
|
@ -101,7 +74,7 @@ var KeyboardShortcut = { |
|
|
|
|
if(!($(":focus").is("input[type=text]") || |
|
|
|
|
$(":focus").is("input[type=password]") || |
|
|
|
|
$(":focus").is("textarea"))) { |
|
|
|
|
var key = self.getKeyboardKey(e).toUpperCase(); |
|
|
|
|
var key = self._getKeyboardKey(e).toUpperCase(); |
|
|
|
|
if(key === "T") { |
|
|
|
|
if(APP.conference.isLocalAudioMuted()) |
|
|
|
|
APP.conference.muteAudio(false); |
|
|
|
@ -112,20 +85,56 @@ var KeyboardShortcut = { |
|
|
|
|
trigger: 'click hover', |
|
|
|
|
content: function() { |
|
|
|
|
return this.getAttribute("content") + |
|
|
|
|
self.getShortcut(this.getAttribute("shortcut")); |
|
|
|
|
self._getShortcut(this.getAttribute("shortcut")); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Registers a new shortcut. |
|
|
|
|
* |
|
|
|
|
* @param shortcutChar the shortcut character triggering the action |
|
|
|
|
* @param shortcutAttr the "shortcut" html element attribute mappring an |
|
|
|
|
* element to this shortcut and used to show the shortcut character on the |
|
|
|
|
* element tooltip |
|
|
|
|
* @param exec the function to be executed when the shortcut is pressed |
|
|
|
|
* @param helpDescription the description of the shortcut that would appear |
|
|
|
|
* in the help menu |
|
|
|
|
*/ |
|
|
|
|
registerShortcut: function( shortcutChar, |
|
|
|
|
shortcutAttr, |
|
|
|
|
exec, |
|
|
|
|
helpDescription) { |
|
|
|
|
_shortcuts[shortcutChar] = { |
|
|
|
|
character: shortcutChar, |
|
|
|
|
shortcutAttr: shortcutAttr, |
|
|
|
|
function: exec |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
if (helpDescription) |
|
|
|
|
this._addShortcutToHelp(shortcutChar, helpDescription); |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Unregisters a shortcut. |
|
|
|
|
* |
|
|
|
|
* @param shortcutChar unregisters the given shortcut, which means it will |
|
|
|
|
* no longer be usable |
|
|
|
|
*/ |
|
|
|
|
unregisterShortcut: function(shortcutChar) { |
|
|
|
|
_shortcuts.remove(shortcutChar); |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* |
|
|
|
|
* @param id indicates the popover associated with the shortcut |
|
|
|
|
* @returns {string} the keyboard shortcut used for the id given |
|
|
|
|
*/ |
|
|
|
|
getShortcut: function (id) { |
|
|
|
|
for (var key in shortcuts) { |
|
|
|
|
if (shortcuts.hasOwnProperty(key)) { |
|
|
|
|
if (shortcuts[key].id === id) { |
|
|
|
|
return " (" + shortcuts[key].character + ")"; |
|
|
|
|
_getShortcut: function (id) { |
|
|
|
|
for (var key in _shortcuts) { |
|
|
|
|
if (_shortcuts.hasOwnProperty(key)) { |
|
|
|
|
if (_shortcuts[key].shortcutAttr === id) { |
|
|
|
|
return " (" + _shortcuts[key].character + ")"; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -135,7 +144,7 @@ var KeyboardShortcut = { |
|
|
|
|
* @param e a KeyboardEvent |
|
|
|
|
* @returns {string} e.key or something close if not supported |
|
|
|
|
*/ |
|
|
|
|
getKeyboardKey: function (e) { |
|
|
|
|
_getKeyboardKey: function (e) { |
|
|
|
|
if (typeof e.key === "string") { |
|
|
|
|
return e.key; |
|
|
|
|
} |
|
|
|
@ -156,6 +165,41 @@ var KeyboardShortcut = { |
|
|
|
|
} else { |
|
|
|
|
return String.fromCharCode(e.which).toLowerCase(); |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Adds the given shortcut to the help dialog. |
|
|
|
|
* |
|
|
|
|
* @param shortcutChar the shortcut character |
|
|
|
|
* @param shortcutDescriptionKey the description of the shortcut |
|
|
|
|
* @private |
|
|
|
|
*/ |
|
|
|
|
_addShortcutToHelp: function (shortcutChar, shortcutDescriptionKey) { |
|
|
|
|
|
|
|
|
|
var listElement = document.createElement("li"); |
|
|
|
|
|
|
|
|
|
var spanElement = document.createElement("span"); |
|
|
|
|
spanElement.className = "item-action"; |
|
|
|
|
|
|
|
|
|
var kbdElement = document.createElement("kbd"); |
|
|
|
|
kbdElement.className = "regular-key"; |
|
|
|
|
kbdElement.innerHTML = shortcutChar; |
|
|
|
|
spanElement.appendChild(kbdElement); |
|
|
|
|
|
|
|
|
|
var descriptionElement = document.createElement("span"); |
|
|
|
|
descriptionElement.className = "item-description"; |
|
|
|
|
descriptionElement.setAttribute("data-i18n", shortcutDescriptionKey); |
|
|
|
|
descriptionElement.innerHTML |
|
|
|
|
= APP.translation.translateString(shortcutDescriptionKey); |
|
|
|
|
|
|
|
|
|
listElement.appendChild(spanElement); |
|
|
|
|
listElement.appendChild(descriptionElement); |
|
|
|
|
|
|
|
|
|
var parentListElement |
|
|
|
|
= document.getElementById("keyboard-shortcuts-list"); |
|
|
|
|
|
|
|
|
|
if (parentListElement) |
|
|
|
|
parentListElement.appendChild(listElement); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|