Attach keyboard shortcuts to features
This commit is contained in:
parent
84834dc4e6
commit
7076ada6f4
|
@ -16,4 +16,9 @@
|
|||
#keyboard-shortcuts .item-action {
|
||||
color: #209EFF;
|
||||
font-size: 14pt;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
#keyboard-shortcuts-list {
|
||||
list-style-type: none;
|
||||
}
|
62
index.html
62
index.html
|
@ -279,67 +279,7 @@
|
|||
<div id="keyboard-shortcuts" class="keyboard-shortcuts" style="display:none;">
|
||||
<div class="header"><h3 data-i18n="keyboardShortcuts.keyboardShortcuts"></h3></div>
|
||||
<div class="content">
|
||||
<ul class="item">
|
||||
<li>
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">M</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.mute"></span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">V</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.videoMute"></span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">C</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.toggleChat"></span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">R</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.raiseHand"></span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">T</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.pushToTalk"></span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">D</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.toggleScreensharing"></span>
|
||||
</li>
|
||||
<li class="item-details">
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">F</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.toggleFilmstrip"></span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">?</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.toggleShortcuts"></span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">0</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.focusLocal"></span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">1-9</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.focusRemote"></span>
|
||||
</li>
|
||||
<ul id="keyboard-shortcuts-list" class="item">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -3,9 +3,15 @@ import UIUtil from '../util/UIUtil';
|
|||
import UIEvents from '../../../service/UI/UIEvents';
|
||||
|
||||
const defaultBottomToolbarButtons = {
|
||||
'chat': '#bottom_toolbar_chat',
|
||||
'contacts': '#bottom_toolbar_contact_list',
|
||||
'filmstrip': '#bottom_toolbar_film_strip'
|
||||
'chat': {
|
||||
id: '#bottom_toolbar_chat'
|
||||
},
|
||||
'contacts': {
|
||||
id: '#bottom_toolbar_contact_list'
|
||||
},
|
||||
'filmstrip': {
|
||||
id: '#bottom_toolbar_film_strip'
|
||||
}
|
||||
};
|
||||
|
||||
const BottomToolbar = {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/* jshint -W101 */
|
||||
import UIUtil from '../util/UIUtil';
|
||||
import UIEvents from '../../../service/UI/UIEvents';
|
||||
import KeyboardShortcut from '../../keyboardshortcut/KeyboardShortcut';
|
||||
|
||||
let roomUrl = null;
|
||||
let emitter = null;
|
||||
|
@ -110,7 +111,8 @@ const buttonHandlers = {
|
|||
},
|
||||
"toolbar_button_fullScreen": function() {
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.fullscreen.enabled');
|
||||
UIUtil.buttonClick("#toolbar_button_fullScreen", "icon-full-screen icon-exit-full-screen");
|
||||
UIUtil.buttonClick("#toolbar_button_fullScreen",
|
||||
"icon-full-screen icon-exit-full-screen");
|
||||
emitter.emit(UIEvents.FULLSCREEN_TOGGLE);
|
||||
},
|
||||
"toolbar_button_sip": function () {
|
||||
|
@ -152,16 +154,64 @@ const buttonHandlers = {
|
|||
}
|
||||
};
|
||||
const defaultToolbarButtons = {
|
||||
'microphone': '#toolbar_button_mute',
|
||||
'camera': '#toolbar_button_camera',
|
||||
'desktop': '#toolbar_button_desktopsharing',
|
||||
'security': '#toolbar_button_security',
|
||||
'invite': '#toolbar_button_link',
|
||||
'chat': '#toolbar_button_chat',
|
||||
'etherpad': '#toolbar_button_etherpad',
|
||||
'fullscreen': '#toolbar_button_fullScreen',
|
||||
'settings': '#toolbar_button_settings',
|
||||
'hangup': '#toolbar_button_hangup'
|
||||
'microphone': {
|
||||
id: '#toolbar_button_mute',
|
||||
shortcut: 'M',
|
||||
shortcutAttr: 'mutePopover',
|
||||
shortcutFunc: function() {
|
||||
JitsiMeetJS.analytics.sendEvent('shortcut.audiomute.toggled');
|
||||
APP.conference.toggleAudioMuted();
|
||||
},
|
||||
shortcutDescription: "keyboardShortcuts.mute"
|
||||
},
|
||||
'camera': {
|
||||
id: '#toolbar_button_camera',
|
||||
shortcut: 'V',
|
||||
shortcutAttr: 'toggleVideoPopover',
|
||||
shortcutFunc: function() {
|
||||
JitsiMeetJS.analytics.sendEvent('shortcut.videomute.toggled');
|
||||
APP.conference.toggleVideoMuted();
|
||||
},
|
||||
shortcutDescription: "keyboardShortcuts.videoMute"
|
||||
},
|
||||
'desktop': {
|
||||
id: '#toolbar_button_desktopsharing',
|
||||
shortcut: 'D',
|
||||
shortcutAttr: 'toggleDesktopSharingPopover',
|
||||
shortcutFunc: function() {
|
||||
JitsiMeetJS.analytics.sendEvent('shortcut.screen.toggled');
|
||||
APP.conference.toggleScreenSharing();
|
||||
},
|
||||
shortcutDescription: "keyboardShortcuts.toggleScreensharing"
|
||||
},
|
||||
'security': {
|
||||
id: '#toolbar_button_security'
|
||||
},
|
||||
'invite': {
|
||||
id: '#toolbar_button_link'
|
||||
},
|
||||
'chat': {
|
||||
id: '#toolbar_button_chat',
|
||||
shortcut: 'C',
|
||||
shortcutAttr: 'toggleChatPopover',
|
||||
shortcutFunc: function() {
|
||||
JitsiMeetJS.analytics.sendEvent('shortcut.chat.toggled');
|
||||
APP.UI.toggleChat();
|
||||
},
|
||||
shortcutDescription: "keyboardShortcuts.toggleChat"
|
||||
},
|
||||
'etherpad': {
|
||||
id: '#toolbar_button_etherpad'
|
||||
},
|
||||
'fullscreen': {
|
||||
id: '#toolbar_button_fullScreen'
|
||||
},
|
||||
'settings': {
|
||||
id: '#toolbar_button_settings'
|
||||
},
|
||||
'hangup': {
|
||||
id: '#toolbar_button_hangup'
|
||||
}
|
||||
};
|
||||
|
||||
function dialpadButtonClicked() {
|
||||
|
@ -197,6 +247,22 @@ const Toolbar = {
|
|||
|
||||
UIUtil.hideDisabledButtons(defaultToolbarButtons);
|
||||
|
||||
Object.keys(defaultToolbarButtons).forEach(
|
||||
id => {
|
||||
if (UIUtil.isButtonEnabled(id)) {
|
||||
var button = defaultToolbarButtons[id];
|
||||
|
||||
if (button.shortcut)
|
||||
KeyboardShortcut.registerShortcut(
|
||||
button.shortcut,
|
||||
button.shortcutAttr,
|
||||
button.shortcutFunc,
|
||||
button.shortcutDescription
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Object.keys(buttonHandlers).forEach(
|
||||
buttonId => $(`#${buttonId}`).click(function(event) {
|
||||
!$(this).prop('disabled') && buttonHandlers[buttonId](event);
|
||||
|
|
|
@ -130,7 +130,7 @@
|
|||
var selector = Object.keys(mappings)
|
||||
.map(function (buttonName) {
|
||||
return UIUtil.isButtonEnabled(buttonName)
|
||||
? null : mappings[buttonName]; })
|
||||
? null : mappings[buttonName].id; })
|
||||
.filter(function (item) { return item; })
|
||||
.join(',');
|
||||
$(selector).hide();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue