Add keyboard navigation options for the main browser windows. Fixes #2895

This commit is contained in:
Khushboo Vashi
2018-02-02 14:28:37 +01:00
committed by Dave Page
parent 2042f89ce0
commit 262d01bf01
16 changed files with 438 additions and 12 deletions

View File

@@ -8,6 +8,7 @@ define('pgadmin.browser', [
'pgadmin.browser.error', 'pgadmin.browser.frame',
'pgadmin.browser.node', 'pgadmin.browser.collection',
'sources/codemirror/addon/fold/pgadmin-sqlfoldcode',
'pgadmin.browser.keyboard',
], function(
gettext, url_for, require, $, _, S, Bootstrap, pgAdmin, Alertify,
codemirror, checkNodeVisibility
@@ -544,7 +545,7 @@ define('pgadmin.browser', [
menus[m.name] = new MenuItem({
name: m.name, label: m.label, module: m.module,
category: m.category, callback: m.callback,
priority: m.priority, data: m.data, url: m.url,
priority: m.priority, data: m.data, url: m.url || '#',
target: m.target, icon: m.icon,
enable: (m.enable == '' ? true : (_.isString(m.enable) &&
m.enable.toLowerCase() == 'false') ?
@@ -678,6 +679,7 @@ define('pgadmin.browser', [
url: url_for('preferences.get_all'),
success: function(res) {
self.preferences_cache = res;
pgBrowser.keyboardNavigation.init();
},
error: function(xhr) {
try {
@@ -1958,8 +1960,8 @@ define('pgadmin.browser', [
pgAdmin.Browser.editor_shortcut_keys.Tab = 'insertSoftTab';
}
window.onbeforeunload = function(ev) {
var e = ev || window.event,
window.onbeforeunload = function() {
var e = window.event,
msg = S(gettext('Are you sure you wish to close the %s browser?')).sprintf(pgBrowser.utils.app_name).value();
// For IE and Firefox prior to version 4
@@ -1971,5 +1973,6 @@ define('pgadmin.browser', [
return msg;
};
return pgAdmin.Browser;
});

View File

@@ -0,0 +1,159 @@
/* eslint-disable */
define(
['underscore', 'underscore.string', 'sources/pgadmin', 'jquery', 'mousetrap'],
function(_, S, pgAdmin, $, Mousetrap) {
'use strict';
var pgBrowser = pgAdmin.Browser = pgAdmin.Browser || {};
pgBrowser.keyboardNavigation = pgBrowser.keyboardNavigation || {};
_.extend(pgBrowser.keyboardNavigation, {
init: function() {
Mousetrap.reset();
if (pgBrowser.preferences_cache.length > 0) {
this.keyboardShortcut = {
'file_shortcut': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'main_menu_file').value),
'object_shortcut': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'main_menu_object').value),
'tools_shortcut': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'main_menu_tools').value),
'help_shortcut': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'main_menu_help').value),
'left_tree_shortcut': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'browser_tree').value),
'tabbed_panel_backward': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'tabbed_panel_backward').value),
'tabbed_panel_forward': pgBrowser.keyboardNavigation.parseShortcutValue(pgBrowser.get_preference('browser', 'tabbed_panel_forward').value)
};
this.shortcutMethods = {
'bindMainMenu': {'shortcuts': [this.keyboardShortcut.file_shortcut,
this.keyboardShortcut.object_shortcut, this.keyboardShortcut.tools_shortcut,
this.keyboardShortcut.help_shortcut]}, // Main menu
'bindRightPanel': {'shortcuts': [this.keyboardShortcut.tabbed_panel_backward, this.keyboardShortcut.tabbed_panel_forward]}, // Main window panels
'bindMainMenuLeft': {'shortcuts': 'left', 'bindElem': '.pg-navbar'}, // Main menu
'bindMainMenuRight': {'shortcuts': 'right', 'bindElem': '.pg-navbar'}, // Main menu
'bindMainMenuUpDown': {'shortcuts': ['up', 'down']}, // Main menu
'bindLeftTree': {'shortcuts': this.keyboardShortcut.left_tree_shortcut}, // Main menu
};
this.bindShortcuts();
}
},
bindShortcuts: function() {
var self = this;
_.each(self.shortcutMethods, function(keyCombo, callback) {
self._bindWithMousetrap(keyCombo.shortcuts, self[callback], keyCombo.bindElem);
});
},
_bindWithMousetrap: function(shortcuts, callback, bindElem) {
if (bindElem) {
var elem = document.querySelector(bindElem);
Mousetrap(elem).bind(shortcuts, function() {
callback.apply(this, arguments);
}.bind(elem));
} else {
Mousetrap.bind(shortcuts, function() {
callback.apply(this, arguments);
});
}
},
attachShortcut: function(shortcut, callback, bindElem) {
this._bindWithMousetrap(shortcut, callback, bindElem);
},
detachShortcut: function(shortcut, bindElem) {
if (bindElem) Mousetrap(bindElem).unbind(shortcut);
else Mousetrap.unbind(shortcut);
},
bindMainMenu: function(e, combo) {
var shortcut_obj = pgAdmin.Browser.keyboardNavigation.keyboardShortcut;
if (combo == shortcut_obj.file_shortcut) $('#mnu_file a.dropdown-toggle').dropdown('toggle');
if (combo == shortcut_obj.object_shortcut) $('#mnu_obj a.dropdown-toggle').first().dropdown('toggle');
if (combo == shortcut_obj.tools_shortcut) $('#mnu_tools a.dropdown-toggle').dropdown('toggle');
if (combo == shortcut_obj.help_shortcut) $('#mnu_help a.dropdown-toggle').dropdown('toggle');
},
bindRightPanel: function(e, combo) {
var allPanels = pgAdmin.Browser.docker.findPanels(),
activePanel = 0,
nextPanel = allPanels.length,
prevPanel = 1,
activePanelId = 0,
activePanelFlag = false,
shortcut_obj = pgAdmin.Browser.keyboardNavigation.keyboardShortcut;
_.each(pgAdmin.Browser.docker.findPanels(), function(panel, index){
if (panel.isVisible() && !activePanelFlag && panel._type != 'browser'){
activePanelId = index;
activePanelFlag = true;
}
});
if (combo == shortcut_obj.tabbed_panel_backward) activePanel = (activePanelId > 0) ? activePanelId - 1 : prevPanel;
else if (combo == shortcut_obj.tabbed_panel_forward) activePanel = (activePanelId < nextPanel) ? activePanelId + 1 : nextPanel;
pgAdmin.Browser.docker.findPanels()[activePanel].focus();
setTimeout(function() {
if (document.activeElement instanceof HTMLIFrameElement) {
document.activeElement.blur();
}
}, 1000);
},
bindMainMenuLeft: function(e) {
var prevMenu;
if ($(e.target).hasClass('menu-link')) { // Menu items
prevMenu = $(e.target).parent().parent().parent().prev('.dropdown');
}
else if ($(e.target).parent().hasClass('dropdown-submenu')) { // Sub menu
$(e.target).parent().toggleClass('open');
return;
}
else { //Menu headers
prevMenu = $(e.target).parent().prev('.dropdown');
}
if (prevMenu.hasClass('hide')) prevMenu = prevMenu.prev('.dropdown'); // Skip hidden menus
prevMenu.find('a:first').dropdown('toggle');
},
bindMainMenuRight: function(e) {
var nextMenu;
if ($(e.target).hasClass('menu-link')) { // Menu items
nextMenu = $(e.target).parent().parent().parent().next('.dropdown');
}
else if ($(e.target).parent().hasClass('dropdown-submenu')) { // Sub menu
$(e.target).parent().toggleClass('open');
return;
}
else { //Menu headers
nextMenu = $(e.target).parent().next('.dropdown');
}
if (nextMenu.hasClass('hide')) nextMenu = nextMenu.next('.dropdown'); // Skip hidden menus
nextMenu.find('a:first').dropdown('toggle');
},
bindMainMenuUpDown: function(e, combo) {
// Handle Sub-menus
if (combo == 'up' && $(e.target).parent().prev().prev('.dropdown-submenu').length > 0) {
$(e.target).parent().prev().prev('.dropdown-submenu').find('a:first').focus();
} else {
if ($(e.target).parent().hasClass('dropdown-submenu')) {
$(e.target).parent().parent().parent().find('a:first').dropdown('toggle');
$(e.target).parent().parent().children().eq(2).find('a:first').focus();
}
}
},
bindLeftTree: function() {
var t = pgAdmin.Browser.tree,
item = t.selected().length > 0 ? t.selected() : t.first();
$('#tree').focus();
t.focus(item);
t.select(item);
},
parseShortcutValue: function(obj) {
var shortcut = "";
if (obj.alt) { shortcut += 'alt+'; }
if (obj.shift) { shortcut += 'shift+'; }
if (obj.control) { shortcut += 'ctrl+'; }
shortcut += String.fromCharCode(obj.key.key_code).toLowerCase();
return shortcut;
}
});
return pgAdmin.keyboardNavigation;
});

View File

@@ -42,7 +42,8 @@ define(
if (!that.showTitle)
myPanel.title(false);
else {
myPanel.title(title || that.title);
var title_elem = '<a href="#" tabindex="0" class="panel-link-heading">' + (title || that.title) + '</a>';
myPanel.title(title_elem);
if (that.icon != '')
myPanel.icon(that.icon);
}