public inbox for [email protected]
help / color / mirror / Atom feed[pgAdmin4][patch] Keyboard accessibility for sub-node control
7+ messages / 2 participants
[nested] [flat]
* [pgAdmin4][patch] Keyboard accessibility for sub-node control
@ 2019-07-08 13:43 Ganesh Jaybhay <[email protected]>
2019-07-09 15:58 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Dave Page <[email protected]>
0 siblings, 1 reply; 7+ messages in thread
From: Ganesh Jaybhay @ 2019-07-08 13:43 UTC (permalink / raw)
To: pgadmin-hackers
Hi Hackers,
Attached is the patch for keyboard accessibility of sub-node control. It
also covers sub-node dialog forward/backward tab navigation with shortcuts.
Kindly review.
Regards,
Ganesh Jaybhay
Attachments:
[application/octet-stream] subnode_control_accessibility.patch (37.4K, 3-subnode_control_accessibility.patch)
download | inline diff:
diff --git a/web/pgadmin/browser/register_browser_preferences.py b/web/pgadmin/browser/register_browser_preferences.py
index 009f1c1..bb5da06 100644
--- a/web/pgadmin/browser/register_browser_preferences.py
+++ b/web/pgadmin/browser/register_browser_preferences.py
@@ -387,3 +387,18 @@ def register_browser_preferences(self):
category_label=gettext('Keyboard shortcuts'),
fields=fields
)
+
+ self.preference.register(
+ 'keyboard_shortcuts',
+ 'add_grid_row',
+ gettext('Add grid row'),
+ 'keyboardshortcut',
+ {
+ 'alt': False,
+ 'shift': True,
+ 'control': True,
+ 'key': {'key_code': 65, 'char': 'a'}
+ },
+ category_label=gettext('Keyboard shortcuts'),
+ fields=fields
+ )
diff --git a/web/pgadmin/browser/static/js/keyboard.js b/web/pgadmin/browser/static/js/keyboard.js
index 9ad59b6..b50d025 100644
--- a/web/pgadmin/browser/static/js/keyboard.js
+++ b/web/pgadmin/browser/static/js/keyboard.js
@@ -41,6 +41,7 @@ _.extend(pgBrowser.keyboardNavigation, {
'direct_debugging': commonUtils.parseShortcutValue(pgBrowser.get_preference('browser', 'direct_debugging').value),
'drop_multiple_objects': commonUtils.parseShortcutValue(pgBrowser.get_preference('browser', 'grid_menu_drop_multiple').value),
'drop_cascade_multiple_objects': commonUtils.parseShortcutValue(pgBrowser.get_preference('browser', 'grid_menu_drop_cascade_multiple').value),
+ 'add_grid_row': commonUtils.parseShortcutValue(pgBrowser.get_preference('browser', 'add_grid_row').value),
};
this.shortcutMethods = {
@@ -61,6 +62,7 @@ _.extend(pgBrowser.keyboardNavigation, {
'bindDirectDebugging': {'shortcuts': this.keyboardShortcut.direct_debugging}, // Sub menu - Direct Debugging
'bindDropMultipleObjects': {'shortcuts': this.keyboardShortcut.drop_multiple_objects}, // Grid Menu Drop Multiple
'bindDropCascadeMultipleObjects': {'shortcuts': this.keyboardShortcut.drop_cascade_multiple_objects}, // Grid Menu Drop Cascade Multiple
+ 'bindAddGridRow': {'shortcuts': this.keyboardShortcut.add_grid_row}, // Subnode Grid Add Row
};
this.bindShortcuts();
}
@@ -330,6 +332,12 @@ _.extend(pgBrowser.keyboardNavigation, {
$('button.delete_multiple_cascade').click();
}
},
+ bindAddGridRow: function() {
+ let subNode = $(document.activeElement).closest('.object.subnode');
+ if($(subNode).length) {
+ $(subNode).find('.add').click();
+ }
+ },
isPropertyPanelVisible: function() {
let isPanelVisible = false;
_.each(pgAdmin.Browser.docker.findPanels(), (panel) => {
diff --git a/web/pgadmin/static/js/backform.pgadmin.js b/web/pgadmin/static/js/backform.pgadmin.js
index b97fc38..156430d 100644
--- a/web/pgadmin/static/js/backform.pgadmin.js
+++ b/web/pgadmin/static/js/backform.pgadmin.js
@@ -10,8 +10,10 @@
define([
'sources/gettext', 'underscore', 'underscore.string', 'jquery',
'backbone', 'backform', 'backgrid', 'codemirror', 'sources/sqleditor_utils',
+ 'sources/keyboard_shortcuts',
'spectrum', 'pgadmin.backgrid', 'select2', 'bootstrap.toggle',
-], function(gettext, _, S, $, Backbone, Backform, Backgrid, CodeMirror, SqlEditorUtils) {
+], function(gettext, _, S, $, Backbone, Backform, Backgrid, CodeMirror,
+ SqlEditorUtils, keyboardShortcuts) {
var pgAdmin = (window.pgAdmin = window.pgAdmin || {}),
pgBrowser = pgAdmin.Browser;
@@ -1269,6 +1271,13 @@ define([
var $dialog = gridBody.append(subNodeGrid);
+ let preferences = pgBrowser.get_preferences_for_module('browser');
+ let addBtn = $dialog.find('.add');
+ // Add title to the buttons
+ $(addBtn)
+ .attr('title',
+ keyboardShortcuts.shortcut_title(gettext('Add new row'),preferences.add_grid_row));
+
// Add button callback
if (!(data.disabled || data.canAdd == false)) {
$dialog.find('button.add').first().on('click',(e) => {
@@ -1554,6 +1563,14 @@ define([
var $dialog = gridBody.append(subNodeGrid);
+ let preferences = pgBrowser.get_preferences_for_module('browser');
+ let addBtn = $dialog.find('.add');
+ // Add title to the buttons
+ $(addBtn)
+ .attr('title',
+ keyboardShortcuts.shortcut_title(gettext('Add new row'),preferences.add_grid_row));
+
+
// Add button callback
$dialog.find('button.add').on('click',(e) => {
e.preventDefault();
diff --git a/web/pgadmin/static/js/backgrid.pgadmin.js b/web/pgadmin/static/js/backgrid.pgadmin.js
index c804609..86cc35c 100644
--- a/web/pgadmin/static/js/backgrid.pgadmin.js
+++ b/web/pgadmin/static/js/backgrid.pgadmin.js
@@ -9,15 +9,18 @@
define([
'sources/gettext', 'underscore', 'jquery', 'backbone', 'backform', 'backgrid', 'alertify',
- 'moment', 'bignumber', 'bootstrap.datetimepicker', 'backgrid.filter',
- 'bootstrap.toggle',
+ 'moment', 'bignumber', 'sources/utils', 'sources/keyboard_shortcuts',
+ 'bootstrap.datetimepicker', 'backgrid.filter', 'bootstrap.toggle',
], function(
- gettext, _, $, Backbone, Backform, Backgrid, Alertify, moment, BigNumber
+ gettext, _, $, Backbone, Backform, Backgrid, Alertify, moment, BigNumber,
+ commonUtils, keyboardShortcuts
) {
/*
* Add mechanism in backgrid to render different types of cells in
* same column;
*/
+ let pgAdmin = (window.pgAdmin = window.pgAdmin || {}),
+ pgBrowser = pgAdmin.Browser;
// Add new property cellFunction in Backgrid.Column.
_.extend(Backgrid.Column.prototype.defaults, {
@@ -37,6 +40,18 @@ define([
},
});
+ // bind shortcut in cell edit mode
+ _.extend(Backgrid.InputCellEditor.prototype.events, {
+ 'keydown': function(e) {
+ let preferences = pgBrowser.get_preferences_for_module('browser');
+ if(keyboardShortcuts.validateShortcutKeys(preferences.add_grid_row,e)) {
+ pgBrowser.keyboardNavigation.bindAddGridRow();
+ } else {
+ Backgrid.InputCellEditor.prototype.saveOrCancel.apply(this, arguments);
+ }
+ },
+ });
+
/* Overriding backgrid sort method.
* As we are getting numeric, integer values as string
* from server side, but on client side javascript truncates
@@ -189,7 +204,7 @@ define([
var ObjectCellEditor = Backgrid.Extension.ObjectCellEditor = Backgrid.CellEditor.extend({
modalTemplate: _.template([
- '<div class="subnode-dialog" tabindex="1">',
+ '<div class="subnode-dialog" tabindex="0">',
' <div class="subnode-body"></div>',
'</div>',
].join('\n')),
@@ -235,6 +250,18 @@ define([
tabPanelClassName: function() {
return 'sub-node-form col-sm-12';
},
+ events: {
+ 'keydown': function (event) {
+ let preferences = pgBrowser.get_preferences_for_module('browser');
+ if(keyboardShortcuts.validateShortcutKeys(preferences.add_grid_row,event)) {
+ pgBrowser.keyboardNavigation.bindAddGridRow();
+ } else if(keyboardShortcuts.validateShortcutKeys(preferences.save_grid_row,event)) {
+ pgBrowser.keyboardNavigation.bindSaveGridRow();
+ } else if(keyboardShortcuts.validateShortcutKeys(preferences.refresh_grid,event)) {
+ pgBrowser.keyboardNavigation.bindRefreshGrid();
+ }
+ },
+ },
});
this.objectView.render();
@@ -315,12 +342,18 @@ define([
editorOptions['el'] = $(this.el);
editorOptions['columns_length'] = this.column.collection.length;
- editorOptions['el'].attr('tabindex', 1);
+ editorOptions['el'].attr('tabindex', 0);
this.listenTo(this.model, 'backgrid:edit', function(model, column, cell, editor) {
if (column.get('name') == this.column.get('name'))
editor.extendWithOptions(editorOptions);
});
+ // Listen for Tab key, open subnode dialog on space key
+ this.$el.on('keydown', function(e) {
+ if (e.keyCode == 32) {
+ $(this).click();
+ }
+ });
},
enterEditMode: function() {
// Notify that we are about to enter in edit mode for current cell.
@@ -342,6 +375,10 @@ define([
this.$el.html(
'<i class=\'fa fa-pencil-square subnode-edit-in-process\' title=\'' + _('Edit row') + '\'></i>'
);
+ let body = $(this.$el).parents()[1],
+ container = $(body).find('.tab-content:first > .tab-pane.active:first');
+ commonUtils.findAndSetFocus(container);
+ pgBrowser.keyboardNavigation.getDialogTabNavigator($(body).find('.subnode-dialog'));
this.model.trigger(
'pg-sub-node:opened', this.model, this
);
@@ -362,14 +399,16 @@ define([
return this;
},
exitEditMode: function() {
- var index = $(this.currentEditor.objectView.el)
- .find('.nav-tabs > .active > a[data-toggle="tab"]').first()
- .data('tabIndex');
- Backgrid.Cell.prototype.exitEditMode.apply(this, arguments);
- this.model.trigger(
- 'pg-sub-node:closed', this, index
- );
- this.grabFocus = true;
+ if(!_.isUndefined(this.currentEditor) || !_.isEmpty(this.currentEditor)) {
+ var index = $(this.currentEditor.objectView.el)
+ .find('.nav-tabs > .active > a[data-toggle="tab"]').first()
+ .data('tabIndex');
+ Backgrid.Cell.prototype.exitEditMode.apply(this, arguments);
+ this.model.trigger(
+ 'pg-sub-node:closed', this, index
+ );
+ this.grabFocus = true;
+ }
},
events: {
'click': function(e) {
@@ -382,6 +421,17 @@ define([
}
e.preventDefault();
},
+ 'keydown': function(e) {
+ var model = this.model;
+ var column = this.column;
+ var command = new Backgrid.Command(e);
+
+ if (command.moveLeft()) {
+ setTimeout(function() {
+ model.trigger('backgrid:edited', model, column, command);
+ }, 20);
+ }
+ },
},
});
@@ -413,7 +463,16 @@ define([
delete_title,
delete_msg,
function() {
+ let tbody = that.el.closest('tbody');
that.model.collection.remove(that.model);
+ let row = $(tbody).find('tr');
+ if(row.length > 0) {
+ // set focus to first tr
+ row.first().children()[0].focus();
+ } else {
+ // set focus to add button
+ $(tbody).closest('.subnode').find('.add').focus();
+ }
},
function() {
return true;
@@ -427,12 +486,54 @@ define([
);
}
},
+ exitEditMode: function() {
+ this.$el.removeClass('editor');
+ },
initialize: function() {
Backgrid.Cell.prototype.initialize.apply(this, arguments);
},
render: function() {
+ var self = this;
this.$el.empty();
+ $(this.$el).attr('tabindex', 0);
this.$el.html('<i class=\'fa fa-trash\' title=\'' + _('Delete row') + '\'></i>');
+ // Listen for Tab/Shift-Tab key
+ this.$el.on('keydown', function(e) {
+ // with keyboard navigation on space key, mark row for deletion
+ if (e.keyCode == 32) {
+ self.$el.click();
+ }
+ var gotoCell;
+ if (e.keyCode == 9 || e.keyCode == 16) {
+ // go to Next Cell & if Shift is also pressed go to Previous Cell
+ gotoCell = e.shiftKey ? self.$el.prev() : self.$el.next();
+ }
+
+ if (gotoCell) {
+ let command = new Backgrid.Command({
+ key: 'Tab',
+ keyCode: 9,
+ which: 9,
+ shiftKey: e.shiftKey,
+ });
+ setTimeout(function() {
+ // When we have Editable Cell
+ if (gotoCell.hasClass('editable')) {
+ e.preventDefault();
+ e.stopPropagation();
+ self.model.trigger('backgrid:edited', self.model,
+ self.column, command);
+ }
+ else {
+ // When we have Non-Editable Cell
+ self.model.trigger('backgrid:edited', self.model,
+ self.column, command);
+ }
+ }, 20);
+ }
+ });
+
+
this.delegateEvents();
return this;
},
@@ -488,6 +589,7 @@ define([
'change input': 'onChange',
'keyup': 'toggleSwitch',
'blur input': 'exitEditMode',
+ 'keydown': 'onKeyDown',
},
toggleSwitch: function(e) {
@@ -497,6 +599,13 @@ define([
}
},
+ onKeyDown: function(e) {
+ let preferences = pgBrowser.get_preferences_for_module('browser');
+ if(keyboardShortcuts.validateShortcutKeys(preferences.add_grid_row,e)) {
+ pgBrowser.keyboardNavigation.bindAddGridRow();
+ }
+ },
+
onChange: function() {
var model = this.model,
column = this.column,
@@ -553,7 +662,11 @@ define([
});
setTimeout(function() {
// When we have Editable Cell
- if (gotoCell.hasClass('editable')) {
+ if (gotoCell.hasClass('editable') && gotoCell.hasClass('edit-cell')) {
+ e.preventDefault();
+ e.stopPropagation();
+ gotoCell.trigger('focus');
+ } else if (gotoCell.hasClass('editable')) {
e.preventDefault();
e.stopPropagation();
self.model.trigger('backgrid:edited', self.model,
@@ -608,8 +721,7 @@ define([
},
saveOrCancel: function (e) {
- var model = this.model;
- var column = this.column;
+ var self = this;
var command = new Backgrid.Command(e);
var blurred = e.type === 'blur';
@@ -617,10 +729,32 @@ define([
if (command.moveUp() || command.moveDown() || command.moveLeft() || command.moveRight() ||
command.save() || blurred) {
- this.exitEditMode();
- e.preventDefault();
- e.stopPropagation();
- model.trigger('backgrid:edited', model, column, command);
+ let gotoCell;
+ // go to Next Cell & if Shift is also pressed go to Previous Cell
+ gotoCell = e.shiftKey ? self.$el.prev() : self.$el.next();
+
+ if (gotoCell) {
+ let command = new Backgrid.Command({
+ key: 'Tab',
+ keyCode: 9,
+ which: 9,
+ shiftKey: e.shiftKey,
+ });
+ setTimeout(function() {
+ // When we have Editable Cell
+ if (gotoCell.hasClass('editable')) {
+ e.preventDefault();
+ e.stopPropagation();
+ self.model.trigger('backgrid:edited', self.model,
+ self.column, command);
+ }
+ else {
+ // When we have Non-Editable Cell
+ self.model.trigger('backgrid:edited', self.model,
+ self.column, command);
+ }
+ }, 20);
+ }
}
},
events: {
diff --git a/web/pgadmin/static/js/dialog_tab_navigator.js b/web/pgadmin/static/js/dialog_tab_navigator.js
index 4472172..37bff6b 100644
--- a/web/pgadmin/static/js/dialog_tab_navigator.js
+++ b/web/pgadmin/static/js/dialog_tab_navigator.js
@@ -46,13 +46,13 @@ class dialogTabNavigator {
if(childTabData) {
var res = this.navigate(shortcut, childTabData.childTab,
- childTabData.childTabPane);
+ childTabData.childTabPane, event);
if (!res) {
- this.navigate(shortcut, this.tabs, currentTabPane);
+ this.navigate(shortcut, this.tabs, currentTabPane, event);
}
} else {
- this.navigate(shortcut, this.tabs, currentTabPane);
+ this.navigate(shortcut, this.tabs, currentTabPane, event);
}
}
@@ -73,16 +73,16 @@ class dialogTabNavigator {
return null;
}
- navigate(shortcut, tabs, tab_pane) {
+ navigate(shortcut, tabs, tab_pane, event) {
if(shortcut == this.dialogTabBackward) {
- return this.navigateBackward(tabs, tab_pane);
+ return this.navigateBackward(tabs, tab_pane, event);
}else if (shortcut == this.dialogTabForward) {
- return this.navigateForward(tabs, tab_pane);
+ return this.navigateForward(tabs, tab_pane, event);
}
return false;
}
- navigateBackward(tabs, tab_pane) {
+ navigateBackward(tabs, tab_pane, event) {
var self = this,
nextTabPane,
innerTabContainer,
@@ -105,6 +105,7 @@ class dialogTabNavigator {
self.tabSwitching = false;
}, 200);
+ event.stopPropagation();
return true;
}
@@ -112,7 +113,7 @@ class dialogTabNavigator {
return false;
}
- navigateForward(tabs, tab_pane) {
+ navigateForward(tabs, tab_pane, event) {
var self = this,
nextTabPane,
innerTabContainer,
@@ -135,6 +136,8 @@ class dialogTabNavigator {
self.tabSwitching = false;
}, 200);
+ event.stopPropagation();
+
return true;
}
this.tabSwitching = false;
diff --git a/web/pgadmin/static/scss/_backgrid.overrides.scss b/web/pgadmin/static/scss/_backgrid.overrides.scss
index b0b7475..41266eb 100644
--- a/web/pgadmin/static/scss/_backgrid.overrides.scss
+++ b/web/pgadmin/static/scss/_backgrid.overrides.scss
@@ -288,6 +288,10 @@ table.backgrid {
background-color: $color-bg-theme !important;
}
+ & td.edit-cell.editor:focus {
+ outline: $input-focus-border-color auto 5px !important;
+ }
+
tr.editor-row {
background-color: $color-gray-light !important;
& > td {
diff --git a/web/pgadmin/static/scss/_pgadmin.style.scss b/web/pgadmin/static/scss/_pgadmin.style.scss
index f5a8877..8f1e248 100644
--- a/web/pgadmin/static/scss/_pgadmin.style.scss
+++ b/web/pgadmin/static/scss/_pgadmin.style.scss
@@ -729,10 +729,17 @@ table tr th {
padding: 0;
}
& button:focus {
- outline: none;
+ outline: $input-focus-border-color auto 5px !important;
}
}
+table tr td {
+ td.edit-cell:focus,
+ td.delete-cell:focus,
+ td.string-cell:focus {
+ outline: $input-focus-border-color auto 5px !important;
+ }
+}
.privilege_label{
font-size: 10px!important;
diff --git a/web/pgadmin/static/vendor/backgrid/backgrid.js b/web/pgadmin/static/vendor/backgrid/backgrid.js
index 963ddca..1b3173b 100644
--- a/web/pgadmin/static/vendor/backgrid/backgrid.js
+++ b/web/pgadmin/static/vendor/backgrid/backgrid.js
@@ -8,32 +8,35 @@
//////////////////////////////////////////////////////////////
/*!
- backgrid
- http://github.com/wyuenho/backgrid
+ backgrid 0.3.8
+ http://github.com/cloudflare/backgrid
- Copyright (c) 2014 Jimmy Yuen Ho Wong and contributors <[email protected]>
+ Copyright (c) 2017 Cloudflare, Inc. and contributors <[email protected]>
Licensed under the MIT license.
*/
-(function (factory) {
+(function (root, factory) {
- // CommonJS
- if (typeof exports == "object") {
- module.exports = factory(module.exports,
- require("underscore"),
- require("backbone"));
- }
- // Browser
- else factory(this, this._, this.Backbone);
-}(function (root, _, Backbone) {
+ if (typeof define === "function" && define.amd) {
+ // AMD (+ global for extensions)
+ define(["underscore", "backbone"], function (_, Backbone) {
+ return (root.Backgrid = factory(_, Backbone));
+ });
+ } else if (typeof exports === "object") {
+ // CommonJS
+ module.exports = factory(require("underscore"), require("backbone"));
+ } else {
+ // Browser
+ root.Backgrid = factory(root._, root.Backbone);
+ }}(this, function (_, Backbone) {
"use strict";
/*
backgrid
- http://github.com/wyuenho/backgrid
+ http://github.com/cloudflare/backgrid
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+ Copyright (c) 2013-present Cloudflare, Inc. and contributors
Licensed under the MIT license.
*/
@@ -72,7 +75,7 @@ function lpad(str, length, padstr) {
var $ = Backbone.$;
-var Backgrid = root.Backgrid = {
+var Backgrid = {
Extension: {},
@@ -180,9 +183,9 @@ _.extend(Command.prototype, {
/*
backgrid
- http://github.com/wyuenho/backgrid
+ http://github.com/cloudflare/backgrid
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+ Copyright (c) 2013-present Cloudflare, Inc. and contributors
Licensed under the MIT license.
*/
@@ -285,7 +288,7 @@ _.extend(NumberFormatter.prototype, {
fromRaw: function (number, model) {
if (_.isNull(number) || _.isUndefined(number)) return '';
- number = number.toFixed(~~this.decimals);
+ number = parseFloat(number).toFixed(~~this.decimals);
var parts = number.split('.');
var integerPart = parts[0];
@@ -625,9 +628,9 @@ _.extend(SelectFormatter.prototype, {
/*
backgrid
- http://github.com/wyuenho/backgrid
+ http://github.com/cloudflare/backgrid
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+ Copyright (c) 2013-present Cloudflare, Inc. and contributors
Licensed under the MIT license.
*/
@@ -825,7 +828,8 @@ var Cell = Backgrid.Cell = Backbone.View.extend({
/** @property */
events: {
- "click": "enterEditMode"
+ "click": "enterEditMode",
+ "focus": "onFocus"
},
/**
@@ -873,9 +877,16 @@ var Cell = Backgrid.Cell = Backbone.View.extend({
}
});
- if (Backgrid.callByNeed(column.editable(), column, model)) $el.addClass("editable");
- if (Backgrid.callByNeed(column.sortable(), column, model)) $el.addClass("sortable");
- if (Backgrid.callByNeed(column.renderable(), column, model)) $el.addClass("renderable");
+ this.updateStateClassesMaybe();
+ },
+
+ updateStateClassesMaybe: function () {
+ var model = this.model;
+ var column = this.column;
+ var $el = this.$el;
+ $el.toggleClass("editable", Backgrid.callByNeed(column.editable(), column, model));
+ $el.toggleClass("sortable", Backgrid.callByNeed(column.sortable(), column, model));
+ $el.toggleClass("renderable", Backgrid.callByNeed(column.renderable(), column, model));
},
/**
@@ -883,9 +894,18 @@ var Cell = Backgrid.Cell = Backbone.View.extend({
model's raw value for this cell's column.
*/
render: function () {
- this.$el.empty();
+ var $el = this.$el;
+ $el.empty();
var model = this.model;
- this.$el.text(this.formatter.fromRaw(model.get(this.column.get("name")), model));
+ var columnName = this.column.get("name");
+ $el.text(this.formatter.fromRaw(model.get(columnName), model));
+ $el.addClass(columnName);
+ if(this.$el.hasClass('string-cell')) {
+ if(Backgrid.callByNeed(this.column.editable(), this.column, this.model)) {
+ $el.attr('tabindex', 0);
+ }
+ }
+ this.updateStateClassesMaybe();
this.delegateEvents();
return this;
},
@@ -935,6 +955,12 @@ var Cell = Backgrid.Cell = Backbone.View.extend({
}
},
+ onFocus: function (e) {
+ if(e.keyCode == 9 && $(this).hasClass('string-cell') && $(this).hasClass('editable')) {
+ $(this).click();
+ }
+ },
+
/**
Put an `error` CSS class on the table cell.
*/
@@ -1408,7 +1434,15 @@ var SelectCellEditor = Backgrid.SelectCellEditor = CellEditor.extend({
},
/** @property {function(Object, ?Object=): string} template */
- template: _.template('<option value="<%- value %>" <%= selected ? \'selected="selected"\' : "" %>><%- text %></option>', null, {variable: null}),
+ template: _.template(
+ '<option value="<%- value %>" <%= selected ? \'selected="selected"\' : "" %>><%- text %></option>',
+ null,
+ {
+ variable : null,
+ evaluate : /<%([\s\S]+?)%>/g,
+ interpolate : /<%=([\s\S]+?)%>/g,
+ escape : /<%-([\s\S]+?)%>/g
+ }),
setOptionValues: function (optionValues) {
this.optionValues = optionValues;
@@ -1651,9 +1685,9 @@ var SelectCell = Backgrid.SelectCell = Cell.extend({
/*
backgrid
- http://github.com/wyuenho/backgrid
+ http://github.com/cloudflare/backgrid
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+ Copyright (c) 2013-present Cloudflare, Inc. and contributors
Licensed under the MIT license.
*/
@@ -1706,19 +1740,20 @@ var Column = Backgrid.Column = Backbone.Model.extend({
this column is sortable. If the value is a string, a method will the same
name will be looked up from the column instance to determine whether the
column should be sortable. The method's signature must be `function
- (Backgrid.Column, Backbone.Model): boolean`.
+ (Backbone.Model): boolean`. The function's context is the column instance.
@cfg {boolean|string|function(): boolean} [defaults.editable=true] Whether
this column is editable. If the value is a string, a method will the same
name will be looked up from the column instance to determine whether the
column should be editable. The method's signature must be `function
- (Backgrid.Column, Backbone.Model): boolean`.
+ (Backbone.Model): boolean`. The function's context is the column instance.
@cfg {boolean|string|function(): boolean} [defaults.renderable=true]
Whether this column is renderable. If the value is a string, a method will
the same name will be looked up from the column instance to determine
whether the column should be renderable. The method's signature must be
- `function (Backrid.Column, Backbone.Model): boolean`.
+ `function (Backbone.Model): boolean`. The function's context is the column
+ instance.
@cfg {Backgrid.CellFormatter | Object | string} [defaults.formatter] The
formatter to use to convert between raw model values and user input.
@@ -1824,24 +1859,33 @@ var Column = Backgrid.Column = Backbone.Model.extend({
}
/**
+ If you cannot always determine whether a column should be sortable before
+ the grid get initialized, you can override this method.
+
@member Backgrid.Column
@protected
@method sortable
- @return {function(Backgrid.Column, Backbone.Model): boolean | boolean}
+ @return {function(Backbone.Model): boolean | boolean}
*/
/**
+ If you cannot always determine whether a column should be editable before
+ the grid get initialized, you can override this method.
+
@member Backgrid.Column
@protected
@method editable
- @return {function(Backgrid.Column, Backbone.Model): boolean | boolean}
+ @return {function(Backbone.Model): boolean | boolean}
*/
/**
+ If you cannot always determine whether a column should be renderable before
+ the grid get initialized, you can override this method.
+
@member Backgrid.Column
@protected
@method renderable
- @return {function(Backgrid.Column, Backbone.Model): boolean | boolean}
+ @return {function(Backbone.Model): boolean | boolean}
*/
});
@@ -1871,9 +1915,9 @@ var Columns = Backgrid.Columns = Backbone.Collection.extend({
/*
backgrid
- http://github.com/wyuenho/backgrid
+ http://github.com/cloudflare/backgrid
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+ Copyright (c) 2013-present Cloudflare, Inc. and contributors
Licensed under the MIT license.
*/
@@ -2020,7 +2064,9 @@ var EmptyRow = Backgrid.EmptyRow = Backbone.View.extend({
var td = document.createElement("td");
td.setAttribute("colspan", this.columns.length);
- td.appendChild(document.createTextNode(_.result(this, "emptyText")));
+ var span = document.createElement("span");
+ span.innerHTML = _.result(this, "emptyText");
+ td.appendChild(span);
this.el.className = "empty";
this.el.appendChild(td);
@@ -2031,9 +2077,9 @@ var EmptyRow = Backgrid.EmptyRow = Backbone.View.extend({
/*
backgrid
- http://github.com/wyuenho/backgrid
+ http://github.com/cloudflare/backgrid
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+ Copyright (c) 2013-present Cloudflare, Inc. and contributors
Licensed under the MIT license.
*/
@@ -2052,7 +2098,7 @@ var HeaderCell = Backgrid.HeaderCell = Backbone.View.extend({
/** @property */
events: {
- "click a": "onClick"
+ "click button": "onClick"
},
/**
@@ -2087,12 +2133,12 @@ var HeaderCell = Backgrid.HeaderCell = Backbone.View.extend({
if (Backgrid.callByNeed(column.sortable(), column, collection)) $el.addClass("sortable");
if (Backgrid.callByNeed(column.renderable(), column, collection)) $el.addClass("renderable");
- this.listenTo(collection.fullCollection || collection, "sort", this.removeCellDirection);
+ this.listenTo(collection.fullCollection || collection, "backgrid:sorted", this.removeCellDirection);
},
/**
- Event handler for the collection's `sort` event. Removes all the CSS
- direction classes.
+ Event handler for the collection's `backgrid:sorted` event. Removes
+ all the CSS direction classes.
*/
removeCellDirection: function () {
this.$el.removeClass("ascending").removeClass("descending");
@@ -2151,7 +2197,7 @@ var HeaderCell = Backgrid.HeaderCell = Backbone.View.extend({
var sortable = Backgrid.callByNeed(column.sortable(), column, this.collection);
var label;
if(sortable){
- label = $("<a>").text(column.get("label")).append("<b class='sort-caret'></b>");
+ label = $("<button>").text(column.get("label")).append("<span class='sort-caret' aria-hidden='true'></span>");
} else {
label = document.createTextNode(column.get("label"));
}
@@ -2173,8 +2219,6 @@ var HeaderCell = Backgrid.HeaderCell = Backbone.View.extend({
*/
var HeaderRow = Backgrid.HeaderRow = Backgrid.Row.extend({
- requiredOptions: ["columns", "collection"],
-
/**
Initializer.
@@ -2259,9 +2303,9 @@ var Header = Backgrid.Header = Backbone.View.extend({
/*
backgrid
- http://github.com/wyuenho/backgrid
+ http://github.com/cloudflare/backgrid
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+ Copyright (c) 2013-present Cloudflare, Inc. and contributors
Licensed under the MIT license.
*/
@@ -2298,7 +2342,7 @@ var Body = Backgrid.Body = Backbone.View.extend({
this.columns = new Columns(this.columns);
}
- this.row = options.row || Row;
+ this.row = options.row || this.row || Row;
this.rows = this.collection.map(function (model) {
var row = new this.row({
columns: this.columns,
@@ -2318,14 +2362,19 @@ var Body = Backgrid.Body = Backbone.View.extend({
this.listenTo(collection, "reset", this.refresh);
this.listenTo(collection, "backgrid:sort", this.sort);
this.listenTo(collection, "backgrid:edited", this.moveToNextCell);
+
+ this.listenTo(this.columns, "add remove", this.updateEmptyRow);
},
_unshiftEmptyRowMayBe: function () {
if (this.rows.length === 0 && this.emptyText != null) {
- this.rows.unshift(new EmptyRow({
+ this.emptyRow = new EmptyRow({
emptyText: this.emptyText,
columns: this.columns
- }));
+ });
+
+ this.rows.unshift(this.emptyRow);
+ return true
}
},
@@ -2413,7 +2462,9 @@ var Body = Backgrid.Body = Backbone.View.extend({
// removeRow() is called directly
if (!options) {
this.collection.remove(model, (options = collection));
- this._unshiftEmptyRowMayBe();
+ if (this._unshiftEmptyRowMayBe()) {
+ this.render();
+ }
return;
}
@@ -2422,12 +2473,25 @@ var Body = Backgrid.Body = Backbone.View.extend({
}
this.rows.splice(options.index, 1);
- this._unshiftEmptyRowMayBe();
+ if (this._unshiftEmptyRowMayBe()) {
+ this.render();
+ }
return this;
},
/**
+ Rerender the EmptyRow which empties the DOM element, creates the td with the
+ updated colspan, and appends it back into the DOM
+ */
+
+ updateEmptyRow: function () {
+ if (this.emptyRow != null) {
+ this.emptyRow.render();
+ }
+ },
+
+ /**
Reinitialize all the rows inside the body and re-render them. Triggers a
Backbone `backgrid:refresh` event from the collection along with the body
instance as its sole parameter when done.
@@ -2503,7 +2567,7 @@ var Body = Backgrid.Body = Backbone.View.extend({
Triggers a Backbone `backgrid:sorted` event from the collection when done
with the column, direction and a reference to the collection.
- @param {Backgrid.Column} column
+ @param {Backgrid.Column|string} column
@param {null|"ascending"|"descending"} direction
See [Backbone.Collection#comparator](http://backbonejs.org/#Collection-comparator)
@@ -2545,19 +2609,20 @@ var Body = Backgrid.Body = Backbone.View.extend({
}
collection.fullCollection.sort();
collection.trigger("backgrid:sorted", column, direction, collection);
+ column.set("direction", direction);
}
else collection.fetch({reset: true, success: function () {
collection.trigger("backgrid:sorted", column, direction, collection);
+ column.set("direction", direction);
}});
}
else {
collection.comparator = comparator;
collection.sort();
collection.trigger("backgrid:sorted", column, direction, collection);
+ column.set("direction", direction);
}
- column.set("direction", direction);
-
return this;
},
@@ -2596,6 +2661,9 @@ var Body = Backgrid.Body = Backbone.View.extend({
var j = this.columns.indexOf(column);
var cell, renderable, editable, m, n;
+ // return if model being edited in a different grid
+ if (j === -1) return this;
+
this.rows[i].cells[j].exitEditMode();
if (command.moveUp() || command.moveDown() || command.moveLeft() ||
@@ -2625,7 +2693,11 @@ var Body = Backgrid.Body = Backbone.View.extend({
cell = this.rows[m].cells[n];
renderable = Backgrid.callByNeed(cell.column.renderable(), cell.column, cell.model);
editable = Backgrid.callByNeed(cell.column.editable(), cell.column, model);
- if (renderable && editable) {
+ if(cell && cell.$el.hasClass('edit-cell') &&
+ !cell.$el.hasClass('privileges') || cell.$el.hasClass('delete-cell')) {
+ model.trigger("backgrid:next", m, n, false);
+ break;
+ } else if (renderable && editable) {
cell.enterEditMode();
model.trigger("backgrid:next", m, n, false);
break;
@@ -2644,9 +2716,9 @@ var Body = Backgrid.Body = Backbone.View.extend({
/*
backgrid
- http://github.com/wyuenho/backgrid
+ http://github.com/cloudflare/backgrid
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+ Copyright (c) 2013-present Cloudflare, Inc. and contributors
Licensed under the MIT license.
*/
@@ -2684,9 +2756,9 @@ var Footer = Backgrid.Footer = Backbone.View.extend({
/*
backgrid
- http://github.com/wyuenho/backgrid
+ http://github.com/cloudflare/backgrid
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+ Copyright (c) 2013-present Cloudflare, Inc. and contributors
Licensed under the MIT license.
*/
@@ -2760,6 +2832,7 @@ var Grid = Backgrid.Grid = Backbone.View.extend({
@param {Object} options
@param {Backbone.Collection.<Backgrid.Columns>|Array.<Backgrid.Column>|Array.<Object>} options.columns Column metadata.
@param {Backbone.Collection} options.collection The collection of tabular model data to display.
+ @param {string} [options.caption=string] An optional caption to be added to the table.
@param {Backgrid.Header} [options.header=Backgrid.Header] An optional Header class to override the default.
@param {Backgrid.Body} [options.body=Backgrid.Body] An optional Body class to override the default.
@param {Backgrid.Row} [options.row=Backgrid.Row] An optional Row class to override the default.
@@ -2769,10 +2842,12 @@ var Grid = Backgrid.Grid = Backbone.View.extend({
// Convert the list of column objects here first so the subviews don't have
// to.
if (!(options.columns instanceof Backbone.Collection)) {
- options.columns = new Columns(options.columns);
+ options.columns = new Columns(options.columns || this.columns);
}
this.columns = options.columns;
+ this.caption = options.caption;
+
var filteredOptions = _.omit(options, ["el", "id", "attributes",
"className", "tagName", "events"]);
@@ -2851,13 +2926,17 @@ var Grid = Backgrid.Grid = Backbone.View.extend({
},
/**
- Renders the grid's header, then footer, then finally the body. Triggers a
+ Renders the grid's caption, then header, then footer, then finally the body. Triggers a
Backbone `backgrid:rendered` event along with a reference to the grid when
the it has successfully been rendered.
*/
render: function () {
this.$el.empty();
+ if (this.caption) {
+ this.$el.append($("<caption>").text(this.caption));
+ }
+
if (this.header) {
this.$el.append(this.header.render().$el);
}
@@ -2888,5 +2967,5 @@ var Grid = Backgrid.Grid = Backbone.View.extend({
}
});
-return Backgrid;
+ return Backgrid;
}));
diff --git a/web/webpack.shim.js b/web/webpack.shim.js
index 8f43b2a..5f2e48c 100644
--- a/web/webpack.shim.js
+++ b/web/webpack.shim.js
@@ -170,7 +170,8 @@ var webpackShimConfig = {
'backbone': path.join(__dirname, './node_modules/backbone/backbone'),
'backbone.undo': path.join(__dirname, './node_modules/backbone-undo/Backbone.Undo'),
'backform': path.join(__dirname, './pgadmin/static/vendor/backform/backform'),
- 'backgrid': path.join(__dirname, './node_modules/backgrid/lib/backgrid'),
+ // 'backgrid': path.join(__dirname, './node_modules/backgrid/lib/backgrid'),
+ 'backgrid': path.join(__dirname, './pgadmin/static/vendor/backgrid/backgrid'),
'bootstrap.datetimepicker': path.join(__dirname, './node_modules/tempusdominus-bootstrap-4/build/js/tempusdominus-bootstrap-4.min'),
'bootstrap.toggle': path.join(__dirname, './node_modules/bootstrap4-toggle/js/bootstrap4-toggle'),
'select2': path.join(__dirname, './node_modules/select2/dist/js/select2.full'),
^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control
2019-07-08 13:43 [pgAdmin4][patch] Keyboard accessibility for sub-node control Ganesh Jaybhay <[email protected]>
@ 2019-07-09 15:58 ` Dave Page <[email protected]>
2019-07-11 05:59 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Ganesh Jaybhay <[email protected]>
0 siblings, 1 reply; 7+ messages in thread
From: Dave Page @ 2019-07-09 15:58 UTC (permalink / raw)
To: Ganesh Jaybhay <[email protected]>; +Cc: pgadmin-hackers
Hi,
What's the ticket number for this? That's a fair amount of code for a
one-line description. There are also no doc changes describing how to
navigate the sub-node control that I can see.
Also; instead of changing the repo used for backgrid, can we not
un-vendorise it?
On Mon, Jul 8, 2019 at 4:49 PM Ganesh Jaybhay <
[email protected]> wrote:
> Hi Hackers,
>
> Attached is the patch for keyboard accessibility of sub-node control. It
> also covers sub-node dialog forward/backward tab navigation with shortcuts.
>
> Kindly review.
>
> Regards,
> Ganesh Jaybhay
>
--
Dave Page
Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake
EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control
2019-07-08 13:43 [pgAdmin4][patch] Keyboard accessibility for sub-node control Ganesh Jaybhay <[email protected]>
2019-07-09 15:58 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Dave Page <[email protected]>
@ 2019-07-11 05:59 ` Ganesh Jaybhay <[email protected]>
2019-07-11 09:14 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Dave Page <[email protected]>
0 siblings, 1 reply; 7+ messages in thread
From: Ganesh Jaybhay @ 2019-07-11 05:59 UTC (permalink / raw)
To: Dave Page <[email protected]>; +Cc: pgadmin-hackers
Hi Dave,
Ticket number 3919 refers to keyboard accessibility issues for sub-node
control and back grid but this patch covers only sub-node control. Should I
create new one?
I have added the screenshot having newly added shortcut and updated
keyboard shortcut rst file. Also moved the code changes from backgrid.js to
backgrid.pgadmin.js.
Please find the attached updated patch.
Regards,
Ganesh Jaybhay
On Tue, Jul 9, 2019 at 9:28 PM Dave Page <[email protected]> wrote:
> Hi,
>
> What's the ticket number for this? That's a fair amount of code for a
> one-line description. There are also no doc changes describing how to
> navigate the sub-node control that I can see.
>
> Also; instead of changing the repo used for backgrid, can we not
> un-vendorise it?
>
> On Mon, Jul 8, 2019 at 4:49 PM Ganesh Jaybhay <
> [email protected]> wrote:
>
>> Hi Hackers,
>>
>> Attached is the patch for keyboard accessibility of sub-node control. It
>> also covers sub-node dialog forward/backward tab navigation with shortcuts.
>>
>> Kindly review.
>>
>> Regards,
>> Ganesh Jaybhay
>>
>
>
> --
> Dave Page
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>
> EnterpriseDB UK: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
Attachments:
[application/x-patch] subnode_control_accessibility_v1.patch (20.8K, 3-subnode_control_accessibility_v1.patch)
download | inline diff:
diff --git a/docs/en_US/images/preferences_browser_keyboard_shortcuts.png b/docs/en_US/images/preferences_browser_keyboard_shortcuts.png
old mode 100755
new mode 100644
index a4088a8..b0044b9
Binary files a/docs/en_US/images/preferences_browser_keyboard_shortcuts.png and b/docs/en_US/images/preferences_browser_keyboard_shortcuts.png differ
diff --git a/docs/en_US/keyboard_shortcuts.rst b/docs/en_US/keyboard_shortcuts.rst
index 360efb3..6f3727d 100644
--- a/docs/en_US/keyboard_shortcuts.rst
+++ b/docs/en_US/keyboard_shortcuts.rst
@@ -63,6 +63,8 @@ Use the shortcuts below to navigate the tabsets on dialogs:
+----------------------------+-------------------------------------------------------+
| Control+Shift+] | Dialog tab forward |
+----------------------------+-------------------------------------------------------+
+ | Control+Shift+A | Add row in Grid |
+ +----------------------------+-------------------------------------------------------+
SQL Editors
***********
diff --git a/web/pgadmin/browser/register_browser_preferences.py b/web/pgadmin/browser/register_browser_preferences.py
index 009f1c1..bb5da06 100644
--- a/web/pgadmin/browser/register_browser_preferences.py
+++ b/web/pgadmin/browser/register_browser_preferences.py
@@ -387,3 +387,18 @@ def register_browser_preferences(self):
category_label=gettext('Keyboard shortcuts'),
fields=fields
)
+
+ self.preference.register(
+ 'keyboard_shortcuts',
+ 'add_grid_row',
+ gettext('Add grid row'),
+ 'keyboardshortcut',
+ {
+ 'alt': False,
+ 'shift': True,
+ 'control': True,
+ 'key': {'key_code': 65, 'char': 'a'}
+ },
+ category_label=gettext('Keyboard shortcuts'),
+ fields=fields
+ )
diff --git a/web/pgadmin/browser/static/js/keyboard.js b/web/pgadmin/browser/static/js/keyboard.js
index 9ad59b6..b50d025 100644
--- a/web/pgadmin/browser/static/js/keyboard.js
+++ b/web/pgadmin/browser/static/js/keyboard.js
@@ -41,6 +41,7 @@ _.extend(pgBrowser.keyboardNavigation, {
'direct_debugging': commonUtils.parseShortcutValue(pgBrowser.get_preference('browser', 'direct_debugging').value),
'drop_multiple_objects': commonUtils.parseShortcutValue(pgBrowser.get_preference('browser', 'grid_menu_drop_multiple').value),
'drop_cascade_multiple_objects': commonUtils.parseShortcutValue(pgBrowser.get_preference('browser', 'grid_menu_drop_cascade_multiple').value),
+ 'add_grid_row': commonUtils.parseShortcutValue(pgBrowser.get_preference('browser', 'add_grid_row').value),
};
this.shortcutMethods = {
@@ -61,6 +62,7 @@ _.extend(pgBrowser.keyboardNavigation, {
'bindDirectDebugging': {'shortcuts': this.keyboardShortcut.direct_debugging}, // Sub menu - Direct Debugging
'bindDropMultipleObjects': {'shortcuts': this.keyboardShortcut.drop_multiple_objects}, // Grid Menu Drop Multiple
'bindDropCascadeMultipleObjects': {'shortcuts': this.keyboardShortcut.drop_cascade_multiple_objects}, // Grid Menu Drop Cascade Multiple
+ 'bindAddGridRow': {'shortcuts': this.keyboardShortcut.add_grid_row}, // Subnode Grid Add Row
};
this.bindShortcuts();
}
@@ -330,6 +332,12 @@ _.extend(pgBrowser.keyboardNavigation, {
$('button.delete_multiple_cascade').click();
}
},
+ bindAddGridRow: function() {
+ let subNode = $(document.activeElement).closest('.object.subnode');
+ if($(subNode).length) {
+ $(subNode).find('.add').click();
+ }
+ },
isPropertyPanelVisible: function() {
let isPanelVisible = false;
_.each(pgAdmin.Browser.docker.findPanels(), (panel) => {
diff --git a/web/pgadmin/static/js/backform.pgadmin.js b/web/pgadmin/static/js/backform.pgadmin.js
index b97fc38..156430d 100644
--- a/web/pgadmin/static/js/backform.pgadmin.js
+++ b/web/pgadmin/static/js/backform.pgadmin.js
@@ -10,8 +10,10 @@
define([
'sources/gettext', 'underscore', 'underscore.string', 'jquery',
'backbone', 'backform', 'backgrid', 'codemirror', 'sources/sqleditor_utils',
+ 'sources/keyboard_shortcuts',
'spectrum', 'pgadmin.backgrid', 'select2', 'bootstrap.toggle',
-], function(gettext, _, S, $, Backbone, Backform, Backgrid, CodeMirror, SqlEditorUtils) {
+], function(gettext, _, S, $, Backbone, Backform, Backgrid, CodeMirror,
+ SqlEditorUtils, keyboardShortcuts) {
var pgAdmin = (window.pgAdmin = window.pgAdmin || {}),
pgBrowser = pgAdmin.Browser;
@@ -1269,6 +1271,13 @@ define([
var $dialog = gridBody.append(subNodeGrid);
+ let preferences = pgBrowser.get_preferences_for_module('browser');
+ let addBtn = $dialog.find('.add');
+ // Add title to the buttons
+ $(addBtn)
+ .attr('title',
+ keyboardShortcuts.shortcut_title(gettext('Add new row'),preferences.add_grid_row));
+
// Add button callback
if (!(data.disabled || data.canAdd == false)) {
$dialog.find('button.add').first().on('click',(e) => {
@@ -1554,6 +1563,14 @@ define([
var $dialog = gridBody.append(subNodeGrid);
+ let preferences = pgBrowser.get_preferences_for_module('browser');
+ let addBtn = $dialog.find('.add');
+ // Add title to the buttons
+ $(addBtn)
+ .attr('title',
+ keyboardShortcuts.shortcut_title(gettext('Add new row'),preferences.add_grid_row));
+
+
// Add button callback
$dialog.find('button.add').on('click',(e) => {
e.preventDefault();
diff --git a/web/pgadmin/static/js/backgrid.pgadmin.js b/web/pgadmin/static/js/backgrid.pgadmin.js
index c804609..0d968aa 100644
--- a/web/pgadmin/static/js/backgrid.pgadmin.js
+++ b/web/pgadmin/static/js/backgrid.pgadmin.js
@@ -9,15 +9,18 @@
define([
'sources/gettext', 'underscore', 'jquery', 'backbone', 'backform', 'backgrid', 'alertify',
- 'moment', 'bignumber', 'bootstrap.datetimepicker', 'backgrid.filter',
- 'bootstrap.toggle',
+ 'moment', 'bignumber', 'sources/utils', 'sources/keyboard_shortcuts',
+ 'bootstrap.datetimepicker', 'backgrid.filter', 'bootstrap.toggle',
], function(
- gettext, _, $, Backbone, Backform, Backgrid, Alertify, moment, BigNumber
+ gettext, _, $, Backbone, Backform, Backgrid, Alertify, moment, BigNumber,
+ commonUtils, keyboardShortcuts
) {
/*
* Add mechanism in backgrid to render different types of cells in
* same column;
*/
+ let pgAdmin = (window.pgAdmin = window.pgAdmin || {}),
+ pgBrowser = pgAdmin.Browser;
// Add new property cellFunction in Backgrid.Column.
_.extend(Backgrid.Column.prototype.defaults, {
@@ -37,6 +40,18 @@ define([
},
});
+ // bind shortcut in cell edit mode
+ _.extend(Backgrid.InputCellEditor.prototype.events, {
+ 'keydown': function(e) {
+ let preferences = pgBrowser.get_preferences_for_module('browser');
+ if(keyboardShortcuts.validateShortcutKeys(preferences.add_grid_row,e)) {
+ pgBrowser.keyboardNavigation.bindAddGridRow();
+ } else {
+ Backgrid.InputCellEditor.prototype.saveOrCancel.apply(this, arguments);
+ }
+ },
+ });
+
/* Overriding backgrid sort method.
* As we are getting numeric, integer values as string
* from server side, but on client side javascript truncates
@@ -151,6 +166,62 @@ define([
}
};
},
+ moveToNextCell: function (model, column, command) {
+ var i = this.collection.indexOf(model);
+ var j = this.columns.indexOf(column);
+ var cell, renderable, editable, m, n;
+
+ // return if model being edited in a different grid
+ if (j === -1) return this;
+
+ this.rows[i].cells[j].exitEditMode();
+
+ if (command.moveUp() || command.moveDown() || command.moveLeft() ||
+ command.moveRight() || command.save()) {
+ var l = this.columns.length;
+ var maxOffset = l * this.collection.length;
+
+ if (command.moveUp() || command.moveDown()) {
+ m = i + (command.moveUp() ? -1 : 1);
+ var row = this.rows[m];
+ if (row) {
+ cell = row.cells[j];
+ if (Backgrid.callByNeed(cell.column.editable(), cell.column, model)) {
+ cell.enterEditMode();
+ model.trigger('backgrid:next', m, j, false);
+ }
+ }
+ else model.trigger('backgrid:next', m, j, true);
+ }
+ else if (command.moveLeft() || command.moveRight()) {
+ var right = command.moveRight();
+ for (var offset = i * l + j + (right ? 1 : -1);
+ offset >= 0 && offset < maxOffset;
+ right ? offset++ : offset--) {
+ m = ~~(offset / l);
+ n = offset - m * l;
+ cell = this.rows[m].cells[n];
+ renderable = Backgrid.callByNeed(cell.column.renderable(), cell.column, cell.model);
+ editable = Backgrid.callByNeed(cell.column.editable(), cell.column, model);
+ if(cell && cell.$el.hasClass('edit-cell') &&
+ !cell.$el.hasClass('privileges') || cell.$el.hasClass('delete-cell')) {
+ model.trigger('backgrid:next', m, n, false);
+ break;
+ } else if (renderable && editable) {
+ cell.enterEditMode();
+ model.trigger('backgrid:next', m, n, false);
+ break;
+ }
+ }
+
+ if (offset == maxOffset) {
+ model.trigger('backgrid:next', ~~(offset / l), offset - m * l, true);
+ }
+ }
+ }
+
+ return this;
+ },
});
_.extend(Backgrid.Row.prototype, {
@@ -189,7 +260,7 @@ define([
var ObjectCellEditor = Backgrid.Extension.ObjectCellEditor = Backgrid.CellEditor.extend({
modalTemplate: _.template([
- '<div class="subnode-dialog" tabindex="1">',
+ '<div class="subnode-dialog" tabindex="0">',
' <div class="subnode-body"></div>',
'</div>',
].join('\n')),
@@ -235,6 +306,14 @@ define([
tabPanelClassName: function() {
return 'sub-node-form col-sm-12';
},
+ events: {
+ 'keydown': function (event) {
+ let preferences = pgBrowser.get_preferences_for_module('browser');
+ if(keyboardShortcuts.validateShortcutKeys(preferences.add_grid_row,event)) {
+ pgBrowser.keyboardNavigation.bindAddGridRow();
+ }
+ },
+ },
});
this.objectView.render();
@@ -315,12 +394,18 @@ define([
editorOptions['el'] = $(this.el);
editorOptions['columns_length'] = this.column.collection.length;
- editorOptions['el'].attr('tabindex', 1);
+ editorOptions['el'].attr('tabindex', 0);
this.listenTo(this.model, 'backgrid:edit', function(model, column, cell, editor) {
if (column.get('name') == this.column.get('name'))
editor.extendWithOptions(editorOptions);
});
+ // Listen for Tab key, open subnode dialog on space key
+ this.$el.on('keydown', function(e) {
+ if (e.keyCode == 32) {
+ $(this).click();
+ }
+ });
},
enterEditMode: function() {
// Notify that we are about to enter in edit mode for current cell.
@@ -342,6 +427,10 @@ define([
this.$el.html(
'<i class=\'fa fa-pencil-square subnode-edit-in-process\' title=\'' + _('Edit row') + '\'></i>'
);
+ let body = $(this.$el).parents()[1],
+ container = $(body).find('.tab-content:first > .tab-pane.active:first');
+ commonUtils.findAndSetFocus(container);
+ pgBrowser.keyboardNavigation.getDialogTabNavigator($(body).find('.subnode-dialog'));
this.model.trigger(
'pg-sub-node:opened', this.model, this
);
@@ -362,14 +451,16 @@ define([
return this;
},
exitEditMode: function() {
- var index = $(this.currentEditor.objectView.el)
- .find('.nav-tabs > .active > a[data-toggle="tab"]').first()
- .data('tabIndex');
- Backgrid.Cell.prototype.exitEditMode.apply(this, arguments);
- this.model.trigger(
- 'pg-sub-node:closed', this, index
- );
- this.grabFocus = true;
+ if(!_.isUndefined(this.currentEditor) || !_.isEmpty(this.currentEditor)) {
+ var index = $(this.currentEditor.objectView.el)
+ .find('.nav-tabs > .active > a[data-toggle="tab"]').first()
+ .data('tabIndex');
+ Backgrid.Cell.prototype.exitEditMode.apply(this, arguments);
+ this.model.trigger(
+ 'pg-sub-node:closed', this, index
+ );
+ this.grabFocus = true;
+ }
},
events: {
'click': function(e) {
@@ -382,6 +473,17 @@ define([
}
e.preventDefault();
},
+ 'keydown': function(e) {
+ var model = this.model;
+ var column = this.column;
+ var command = new Backgrid.Command(e);
+
+ if (command.moveLeft()) {
+ setTimeout(function() {
+ model.trigger('backgrid:edited', model, column, command);
+ }, 20);
+ }
+ },
},
});
@@ -413,7 +515,16 @@ define([
delete_title,
delete_msg,
function() {
+ let tbody = $(that.el).parents('tbody').eq(0);
that.model.collection.remove(that.model);
+ let row = $(tbody).find('tr');
+ if(row.length > 0) {
+ // set focus to first tr
+ row.first().children()[0].focus();
+ } else {
+ // set focus to add button
+ $(tbody).parents('.subnode').eq(0).find('.add').focus();
+ }
},
function() {
return true;
@@ -427,12 +538,54 @@ define([
);
}
},
+ exitEditMode: function() {
+ this.$el.removeClass('editor');
+ },
initialize: function() {
Backgrid.Cell.prototype.initialize.apply(this, arguments);
},
render: function() {
+ var self = this;
this.$el.empty();
+ $(this.$el).attr('tabindex', 0);
this.$el.html('<i class=\'fa fa-trash\' title=\'' + _('Delete row') + '\'></i>');
+ // Listen for Tab/Shift-Tab key
+ this.$el.on('keydown', function(e) {
+ // with keyboard navigation on space key, mark row for deletion
+ if (e.keyCode == 32) {
+ self.$el.click();
+ }
+ var gotoCell;
+ if (e.keyCode == 9 || e.keyCode == 16) {
+ // go to Next Cell & if Shift is also pressed go to Previous Cell
+ gotoCell = e.shiftKey ? self.$el.prev() : self.$el.next();
+ }
+
+ if (gotoCell) {
+ let command = new Backgrid.Command({
+ key: 'Tab',
+ keyCode: 9,
+ which: 9,
+ shiftKey: e.shiftKey,
+ });
+ setTimeout(function() {
+ // When we have Editable Cell
+ if (gotoCell.hasClass('editable')) {
+ e.preventDefault();
+ e.stopPropagation();
+ self.model.trigger('backgrid:edited', self.model,
+ self.column, command);
+ }
+ else {
+ // When we have Non-Editable Cell
+ self.model.trigger('backgrid:edited', self.model,
+ self.column, command);
+ }
+ }, 20);
+ }
+ });
+
+
this.delegateEvents();
return this;
},
@@ -488,6 +641,7 @@ define([
'change input': 'onChange',
'keyup': 'toggleSwitch',
'blur input': 'exitEditMode',
+ 'keydown': 'onKeyDown',
},
toggleSwitch: function(e) {
@@ -497,6 +651,13 @@ define([
}
},
+ onKeyDown: function(e) {
+ let preferences = pgBrowser.get_preferences_for_module('browser');
+ if(keyboardShortcuts.validateShortcutKeys(preferences.add_grid_row,e)) {
+ pgBrowser.keyboardNavigation.bindAddGridRow();
+ }
+ },
+
onChange: function() {
var model = this.model,
column = this.column,
@@ -553,7 +714,11 @@ define([
});
setTimeout(function() {
// When we have Editable Cell
- if (gotoCell.hasClass('editable')) {
+ if (gotoCell.hasClass('editable') && gotoCell.hasClass('edit-cell')) {
+ e.preventDefault();
+ e.stopPropagation();
+ gotoCell.trigger('focus');
+ } else if (gotoCell.hasClass('editable')) {
e.preventDefault();
e.stopPropagation();
self.model.trigger('backgrid:edited', self.model,
@@ -608,8 +773,7 @@ define([
},
saveOrCancel: function (e) {
- var model = this.model;
- var column = this.column;
+ var self = this;
var command = new Backgrid.Command(e);
var blurred = e.type === 'blur';
@@ -617,10 +781,32 @@ define([
if (command.moveUp() || command.moveDown() || command.moveLeft() || command.moveRight() ||
command.save() || blurred) {
- this.exitEditMode();
- e.preventDefault();
- e.stopPropagation();
- model.trigger('backgrid:edited', model, column, command);
+ let gotoCell;
+ // go to Next Cell & if Shift is also pressed go to Previous Cell
+ gotoCell = e.shiftKey ? self.$el.prev() : self.$el.next();
+
+ if (gotoCell) {
+ let command = new Backgrid.Command({
+ key: 'Tab',
+ keyCode: 9,
+ which: 9,
+ shiftKey: e.shiftKey,
+ });
+ setTimeout(function() {
+ // When we have Editable Cell
+ if (gotoCell.hasClass('editable')) {
+ e.preventDefault();
+ e.stopPropagation();
+ self.model.trigger('backgrid:edited', self.model,
+ self.column, command);
+ }
+ else {
+ // When we have Non-Editable Cell
+ self.model.trigger('backgrid:edited', self.model,
+ self.column, command);
+ }
+ }, 20);
+ }
}
},
events: {
diff --git a/web/pgadmin/static/js/dialog_tab_navigator.js b/web/pgadmin/static/js/dialog_tab_navigator.js
index 4472172..37bff6b 100644
--- a/web/pgadmin/static/js/dialog_tab_navigator.js
+++ b/web/pgadmin/static/js/dialog_tab_navigator.js
@@ -46,13 +46,13 @@ class dialogTabNavigator {
if(childTabData) {
var res = this.navigate(shortcut, childTabData.childTab,
- childTabData.childTabPane);
+ childTabData.childTabPane, event);
if (!res) {
- this.navigate(shortcut, this.tabs, currentTabPane);
+ this.navigate(shortcut, this.tabs, currentTabPane, event);
}
} else {
- this.navigate(shortcut, this.tabs, currentTabPane);
+ this.navigate(shortcut, this.tabs, currentTabPane, event);
}
}
@@ -73,16 +73,16 @@ class dialogTabNavigator {
return null;
}
- navigate(shortcut, tabs, tab_pane) {
+ navigate(shortcut, tabs, tab_pane, event) {
if(shortcut == this.dialogTabBackward) {
- return this.navigateBackward(tabs, tab_pane);
+ return this.navigateBackward(tabs, tab_pane, event);
}else if (shortcut == this.dialogTabForward) {
- return this.navigateForward(tabs, tab_pane);
+ return this.navigateForward(tabs, tab_pane, event);
}
return false;
}
- navigateBackward(tabs, tab_pane) {
+ navigateBackward(tabs, tab_pane, event) {
var self = this,
nextTabPane,
innerTabContainer,
@@ -105,6 +105,7 @@ class dialogTabNavigator {
self.tabSwitching = false;
}, 200);
+ event.stopPropagation();
return true;
}
@@ -112,7 +113,7 @@ class dialogTabNavigator {
return false;
}
- navigateForward(tabs, tab_pane) {
+ navigateForward(tabs, tab_pane, event) {
var self = this,
nextTabPane,
innerTabContainer,
@@ -135,6 +136,8 @@ class dialogTabNavigator {
self.tabSwitching = false;
}, 200);
+ event.stopPropagation();
+
return true;
}
this.tabSwitching = false;
diff --git a/web/pgadmin/static/scss/_backgrid.overrides.scss b/web/pgadmin/static/scss/_backgrid.overrides.scss
index b0b7475..41266eb 100644
--- a/web/pgadmin/static/scss/_backgrid.overrides.scss
+++ b/web/pgadmin/static/scss/_backgrid.overrides.scss
@@ -288,6 +288,10 @@ table.backgrid {
background-color: $color-bg-theme !important;
}
+ & td.edit-cell.editor:focus {
+ outline: $input-focus-border-color auto 5px !important;
+ }
+
tr.editor-row {
background-color: $color-gray-light !important;
& > td {
diff --git a/web/pgadmin/static/scss/_pgadmin.style.scss b/web/pgadmin/static/scss/_pgadmin.style.scss
index f5a8877..8f1e248 100644
--- a/web/pgadmin/static/scss/_pgadmin.style.scss
+++ b/web/pgadmin/static/scss/_pgadmin.style.scss
@@ -729,10 +729,17 @@ table tr th {
padding: 0;
}
& button:focus {
- outline: none;
+ outline: $input-focus-border-color auto 5px !important;
}
}
+table tr td {
+ td.edit-cell:focus,
+ td.delete-cell:focus,
+ td.string-cell:focus {
+ outline: $input-focus-border-color auto 5px !important;
+ }
+}
.privilege_label{
font-size: 10px!important;
^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control
2019-07-08 13:43 [pgAdmin4][patch] Keyboard accessibility for sub-node control Ganesh Jaybhay <[email protected]>
2019-07-09 15:58 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Dave Page <[email protected]>
2019-07-11 05:59 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Ganesh Jaybhay <[email protected]>
@ 2019-07-11 09:14 ` Dave Page <[email protected]>
2019-07-11 10:19 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Dave Page <[email protected]>
0 siblings, 1 reply; 7+ messages in thread
From: Dave Page @ 2019-07-11 09:14 UTC (permalink / raw)
To: Ganesh Jaybhay <[email protected]>; +Cc: pgadmin-hackers
Thanks - patch applied with some doc tweaks.
No need for a new ticket!
On Thu, Jul 11, 2019 at 7:00 AM Ganesh Jaybhay <
[email protected]> wrote:
> Hi Dave,
>
> Ticket number 3919 refers to keyboard accessibility issues for sub-node
> control and back grid but this patch covers only sub-node control. Should I
> create new one?
> I have added the screenshot having newly added shortcut and updated
> keyboard shortcut rst file. Also moved the code changes from backgrid.js to
> backgrid.pgadmin.js.
>
> Please find the attached updated patch.
>
> Regards,
> Ganesh Jaybhay
>
> On Tue, Jul 9, 2019 at 9:28 PM Dave Page <[email protected]> wrote:
>
>> Hi,
>>
>> What's the ticket number for this? That's a fair amount of code for a
>> one-line description. There are also no doc changes describing how to
>> navigate the sub-node control that I can see.
>>
>> Also; instead of changing the repo used for backgrid, can we not
>> un-vendorise it?
>>
>> On Mon, Jul 8, 2019 at 4:49 PM Ganesh Jaybhay <
>> [email protected]> wrote:
>>
>>> Hi Hackers,
>>>
>>> Attached is the patch for keyboard accessibility of sub-node control. It
>>> also covers sub-node dialog forward/backward tab navigation with shortcuts.
>>>
>>> Kindly review.
>>>
>>> Regards,
>>> Ganesh Jaybhay
>>>
>>
>>
>> --
>> Dave Page
>> Blog: http://pgsnake.blogspot.com
>> Twitter: @pgsnake
>>
>> EnterpriseDB UK: http://www.enterprisedb.com
>> The Enterprise PostgreSQL Company
>>
>
--
Dave Page
Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake
EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control
2019-07-08 13:43 [pgAdmin4][patch] Keyboard accessibility for sub-node control Ganesh Jaybhay <[email protected]>
2019-07-09 15:58 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Dave Page <[email protected]>
2019-07-11 05:59 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Ganesh Jaybhay <[email protected]>
2019-07-11 09:14 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Dave Page <[email protected]>
@ 2019-07-11 10:19 ` Dave Page <[email protected]>
2019-07-11 18:39 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Ganesh Jaybhay <[email protected]>
0 siblings, 1 reply; 7+ messages in thread
From: Dave Page @ 2019-07-11 10:19 UTC (permalink / raw)
To: Ganesh Jaybhay <[email protected]>; +Cc: pgadmin-hackers
Hi Ganesh,
It looks like this has broken the Jasmine tests (which I admit I forgot to
run before committing). Can you fix ASAP please?
Thanks.
On Thu, Jul 11, 2019 at 10:14 AM Dave Page <[email protected]> wrote:
> Thanks - patch applied with some doc tweaks.
>
> No need for a new ticket!
>
> On Thu, Jul 11, 2019 at 7:00 AM Ganesh Jaybhay <
> [email protected]> wrote:
>
>> Hi Dave,
>>
>> Ticket number 3919 refers to keyboard accessibility issues for sub-node
>> control and back grid but this patch covers only sub-node control. Should I
>> create new one?
>> I have added the screenshot having newly added shortcut and updated
>> keyboard shortcut rst file. Also moved the code changes from backgrid.js to
>> backgrid.pgadmin.js.
>>
>> Please find the attached updated patch.
>>
>> Regards,
>> Ganesh Jaybhay
>>
>> On Tue, Jul 9, 2019 at 9:28 PM Dave Page <[email protected]> wrote:
>>
>>> Hi,
>>>
>>> What's the ticket number for this? That's a fair amount of code for a
>>> one-line description. There are also no doc changes describing how to
>>> navigate the sub-node control that I can see.
>>>
>>> Also; instead of changing the repo used for backgrid, can we not
>>> un-vendorise it?
>>>
>>> On Mon, Jul 8, 2019 at 4:49 PM Ganesh Jaybhay <
>>> [email protected]> wrote:
>>>
>>>> Hi Hackers,
>>>>
>>>> Attached is the patch for keyboard accessibility of sub-node control.
>>>> It also covers sub-node dialog forward/backward tab navigation with
>>>> shortcuts.
>>>>
>>>> Kindly review.
>>>>
>>>> Regards,
>>>> Ganesh Jaybhay
>>>>
>>>
>>>
>>> --
>>> Dave Page
>>> Blog: http://pgsnake.blogspot.com
>>> Twitter: @pgsnake
>>>
>>> EnterpriseDB UK: http://www.enterprisedb.com
>>> The Enterprise PostgreSQL Company
>>>
>>
>
> --
> Dave Page
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>
> EnterpriseDB UK: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
--
Dave Page
Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake
EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control
2019-07-08 13:43 [pgAdmin4][patch] Keyboard accessibility for sub-node control Ganesh Jaybhay <[email protected]>
2019-07-09 15:58 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Dave Page <[email protected]>
2019-07-11 05:59 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Ganesh Jaybhay <[email protected]>
2019-07-11 09:14 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Dave Page <[email protected]>
2019-07-11 10:19 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Dave Page <[email protected]>
@ 2019-07-11 18:39 ` Ganesh Jaybhay <[email protected]>
2019-07-12 09:06 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Dave Page <[email protected]>
0 siblings, 1 reply; 7+ messages in thread
From: Ganesh Jaybhay @ 2019-07-11 18:39 UTC (permalink / raw)
To: Dave Page <[email protected]>; +Cc: pgadmin-hackers
Hi Dave,
Please find the attached patch for jasmine tests fix. Patch also includes
fixes for edit/delete cell focus on IE by Murtuza.
Regards,
Ganesh Jaybhay
On Thu, Jul 11, 2019 at 3:49 PM Dave Page <[email protected]> wrote:
> Hi Ganesh,
>
> It looks like this has broken the Jasmine tests (which I admit I forgot to
> run before committing). Can you fix ASAP please?
>
> Thanks.
>
> On Thu, Jul 11, 2019 at 10:14 AM Dave Page <[email protected]> wrote:
>
>> Thanks - patch applied with some doc tweaks.
>>
>> No need for a new ticket!
>>
>> On Thu, Jul 11, 2019 at 7:00 AM Ganesh Jaybhay <
>> [email protected]> wrote:
>>
>>> Hi Dave,
>>>
>>> Ticket number 3919 refers to keyboard accessibility issues for sub-node
>>> control and back grid but this patch covers only sub-node control. Should I
>>> create new one?
>>> I have added the screenshot having newly added shortcut and updated
>>> keyboard shortcut rst file. Also moved the code changes from backgrid.js to
>>> backgrid.pgadmin.js.
>>>
>>> Please find the attached updated patch.
>>>
>>> Regards,
>>> Ganesh Jaybhay
>>>
>>> On Tue, Jul 9, 2019 at 9:28 PM Dave Page <[email protected]> wrote:
>>>
>>>> Hi,
>>>>
>>>> What's the ticket number for this? That's a fair amount of code for a
>>>> one-line description. There are also no doc changes describing how to
>>>> navigate the sub-node control that I can see.
>>>>
>>>> Also; instead of changing the repo used for backgrid, can we not
>>>> un-vendorise it?
>>>>
>>>> On Mon, Jul 8, 2019 at 4:49 PM Ganesh Jaybhay <
>>>> [email protected]> wrote:
>>>>
>>>>> Hi Hackers,
>>>>>
>>>>> Attached is the patch for keyboard accessibility of sub-node control.
>>>>> It also covers sub-node dialog forward/backward tab navigation with
>>>>> shortcuts.
>>>>>
>>>>> Kindly review.
>>>>>
>>>>> Regards,
>>>>> Ganesh Jaybhay
>>>>>
>>>>
>>>>
>>>> --
>>>> Dave Page
>>>> Blog: http://pgsnake.blogspot.com
>>>> Twitter: @pgsnake
>>>>
>>>> EnterpriseDB UK: http://www.enterprisedb.com
>>>> The Enterprise PostgreSQL Company
>>>>
>>>
>>
>> --
>> Dave Page
>> Blog: http://pgsnake.blogspot.com
>> Twitter: @pgsnake
>>
>> EnterpriseDB UK: http://www.enterprisedb.com
>> The Enterprise PostgreSQL Company
>>
>
>
> --
> Dave Page
> Blog: http://pgsnake.blogspot.com
> Twitter: @pgsnake
>
> EnterpriseDB UK: http://www.enterprisedb.com
> The Enterprise PostgreSQL Company
>
Attachments:
[application/x-patch] jasmine_test_fix.patch (4.2K, 3-jasmine_test_fix.patch)
download | inline diff:
diff --git a/web/pgadmin/static/js/backgrid.pgadmin.js b/web/pgadmin/static/js/backgrid.pgadmin.js
index 0d968aa..8275138 100644
--- a/web/pgadmin/static/js/backgrid.pgadmin.js
+++ b/web/pgadmin/static/js/backgrid.pgadmin.js
@@ -206,6 +206,11 @@ define([
if(cell && cell.$el.hasClass('edit-cell') &&
!cell.$el.hasClass('privileges') || cell.$el.hasClass('delete-cell')) {
model.trigger('backgrid:next', m, n, false);
+ if(cell.$el.hasClass('delete-cell')) {
+ setTimeout(function(){
+ $(cell.$el).trigger('focus');
+ }, 50);
+ }
break;
} else if (renderable && editable) {
cell.enterEditMode();
diff --git a/web/pgadmin/static/scss/_pgadmin.style.scss b/web/pgadmin/static/scss/_pgadmin.style.scss
index 8f1e248..082e82c 100644
--- a/web/pgadmin/static/scss/_pgadmin.style.scss
+++ b/web/pgadmin/static/scss/_pgadmin.style.scss
@@ -741,6 +741,17 @@ table tr td {
}
}
+/* Specific to IE11 where we want to highlight the focus on grid buttons */
+@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
+ table tr td {
+ td.edit-cell:focus,
+ td.delete-cell:focus,
+ td.string-cell:focus {
+ border: 2px solid $input-focus-border-color !important;;
+ }
+ }
+}
+
.privilege_label{
font-size: 10px!important;
}
diff --git a/web/regression/javascript/dialog_tab_navigator_spec.js b/web/regression/javascript/dialog_tab_navigator_spec.js
index 8e86fc8..60e4bdd 100644
--- a/web/regression/javascript/dialog_tab_navigator_spec.js
+++ b/web/regression/javascript/dialog_tab_navigator_spec.js
@@ -11,7 +11,7 @@ import $ from 'jquery';
import 'bootstrap';
describe('dialogTabNavigator', function () {
- let dialog, tabNavigator, backward_shortcut, forward_shortcut;
+ let dialog, tabNavigator, backward_shortcut, forward_shortcut, fakeEvent;
beforeEach(() => {
dialog = $('<div tabindex="1" class="backform-tab" role="tabpanel">'+
@@ -68,6 +68,9 @@ describe('dialogTabNavigator', function () {
tabNavigator = new dialogTabNavigator.dialogTabNavigator(
dialog, backward_shortcut, forward_shortcut);
+
+ fakeEvent = { stopPropagation: () => true };
+
});
describe('navigate', function () {
@@ -79,7 +82,7 @@ describe('dialogTabNavigator', function () {
});
it('navigate backward', function () {
- tabNavigator.onKeyboardEvent({}, 'shift+ctrl+[');
+ tabNavigator.onKeyboardEvent(fakeEvent, 'shift+ctrl+[');
expect(tabNavigator.navigateBackward).toHaveBeenCalled();
@@ -88,7 +91,7 @@ describe('dialogTabNavigator', function () {
});
it('navigate forward', function () {
- tabNavigator.onKeyboardEvent({}, 'shift+ctrl+]');
+ tabNavigator.onKeyboardEvent(fakeEvent, 'shift+ctrl+]');
expect(tabNavigator.navigateForward).toHaveBeenCalled();
@@ -97,7 +100,7 @@ describe('dialogTabNavigator', function () {
});
it('should not navigate', function () {
- tabNavigator.onKeyboardEvent({}, 'shift+ctrl+a');
+ tabNavigator.onKeyboardEvent(fakeEvent, 'shift+ctrl+a');
expect(tabNavigator.navigateForward).not.toHaveBeenCalled();
@@ -115,7 +118,8 @@ describe('dialogTabNavigator', function () {
navigateForwardResult = tabNavigator.navigateForward(
dialog.find('ul.nav-tabs:first'),
- dialog.find('div#1')
+ dialog.find('div#1'),
+ fakeEvent
);
});
@@ -141,7 +145,8 @@ describe('dialogTabNavigator', function () {
navigateForwardResult = tabNavigator.navigateForward(
dialog.find('ul.nav-tabs:first'),
- dialog.find('div#1')
+ dialog.find('div#1'),
+ fakeEvent
);
});
@@ -165,7 +170,8 @@ describe('dialogTabNavigator', function () {
navigateBackwardResult = tabNavigator.navigateBackward(
dialog.find('ul.nav-tabs:first'),
- dialog.find('div#1')
+ dialog.find('div#1'),
+ fakeEvent
);
});
@@ -184,7 +190,8 @@ describe('dialogTabNavigator', function () {
navigateBackwardResult = tabNavigator.navigateBackward(
dialog.find('ul.nav-tabs:first'),
- dialog.find('div#1')
+ dialog.find('div#1'),
+ fakeEvent
);
});
^ permalink raw reply [nested|flat] 7+ messages in thread
* Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control
2019-07-08 13:43 [pgAdmin4][patch] Keyboard accessibility for sub-node control Ganesh Jaybhay <[email protected]>
2019-07-09 15:58 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Dave Page <[email protected]>
2019-07-11 05:59 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Ganesh Jaybhay <[email protected]>
2019-07-11 09:14 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Dave Page <[email protected]>
2019-07-11 10:19 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Dave Page <[email protected]>
2019-07-11 18:39 ` Re: [pgAdmin4][patch] Keyboard accessibility for sub-node control Ganesh Jaybhay <[email protected]>
@ 2019-07-12 09:06 ` Dave Page <[email protected]>
0 siblings, 0 replies; 7+ messages in thread
From: Dave Page @ 2019-07-12 09:06 UTC (permalink / raw)
To: Ganesh Jaybhay <[email protected]>; +Cc: pgadmin-hackers
Thanks - committed as the IE fixes, with the Jasmine stuff as a bonus :-)
On Thu, Jul 11, 2019 at 7:40 PM Ganesh Jaybhay <
[email protected]> wrote:
> Hi Dave,
>
> Please find the attached patch for jasmine tests fix. Patch also includes
> fixes for edit/delete cell focus on IE by Murtuza.
>
> Regards,
>
> Ganesh Jaybhay
>
> On Thu, Jul 11, 2019 at 3:49 PM Dave Page <[email protected]> wrote:
>
>> Hi Ganesh,
>>
>> It looks like this has broken the Jasmine tests (which I admit I forgot
>> to run before committing). Can you fix ASAP please?
>>
>> Thanks.
>>
>> On Thu, Jul 11, 2019 at 10:14 AM Dave Page <[email protected]> wrote:
>>
>>> Thanks - patch applied with some doc tweaks.
>>>
>>> No need for a new ticket!
>>>
>>> On Thu, Jul 11, 2019 at 7:00 AM Ganesh Jaybhay <
>>> [email protected]> wrote:
>>>
>>>> Hi Dave,
>>>>
>>>> Ticket number 3919 refers to keyboard accessibility issues for sub-node
>>>> control and back grid but this patch covers only sub-node control. Should I
>>>> create new one?
>>>> I have added the screenshot having newly added shortcut and updated
>>>> keyboard shortcut rst file. Also moved the code changes from backgrid.js to
>>>> backgrid.pgadmin.js.
>>>>
>>>> Please find the attached updated patch.
>>>>
>>>> Regards,
>>>> Ganesh Jaybhay
>>>>
>>>> On Tue, Jul 9, 2019 at 9:28 PM Dave Page <[email protected]> wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> What's the ticket number for this? That's a fair amount of code for a
>>>>> one-line description. There are also no doc changes describing how to
>>>>> navigate the sub-node control that I can see.
>>>>>
>>>>> Also; instead of changing the repo used for backgrid, can we not
>>>>> un-vendorise it?
>>>>>
>>>>> On Mon, Jul 8, 2019 at 4:49 PM Ganesh Jaybhay <
>>>>> [email protected]> wrote:
>>>>>
>>>>>> Hi Hackers,
>>>>>>
>>>>>> Attached is the patch for keyboard accessibility of sub-node control.
>>>>>> It also covers sub-node dialog forward/backward tab navigation with
>>>>>> shortcuts.
>>>>>>
>>>>>> Kindly review.
>>>>>>
>>>>>> Regards,
>>>>>> Ganesh Jaybhay
>>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> Dave Page
>>>>> Blog: http://pgsnake.blogspot.com
>>>>> Twitter: @pgsnake
>>>>>
>>>>> EnterpriseDB UK: http://www.enterprisedb.com
>>>>> The Enterprise PostgreSQL Company
>>>>>
>>>>
>>>
>>> --
>>> Dave Page
>>> Blog: http://pgsnake.blogspot.com
>>> Twitter: @pgsnake
>>>
>>> EnterpriseDB UK: http://www.enterprisedb.com
>>> The Enterprise PostgreSQL Company
>>>
>>
>>
>> --
>> Dave Page
>> Blog: http://pgsnake.blogspot.com
>> Twitter: @pgsnake
>>
>> EnterpriseDB UK: http://www.enterprisedb.com
>> The Enterprise PostgreSQL Company
>>
>
--
Dave Page
Blog: http://pgsnake.blogspot.com
Twitter: @pgsnake
EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
^ permalink raw reply [nested|flat] 7+ messages in thread
end of thread, other threads:[~2019-07-12 09:06 UTC | newest]
Thread overview: 7+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2019-07-08 13:43 [pgAdmin4][patch] Keyboard accessibility for sub-node control Ganesh Jaybhay <[email protected]>
2019-07-09 15:58 ` Dave Page <[email protected]>
2019-07-11 05:59 ` Ganesh Jaybhay <[email protected]>
2019-07-11 09:14 ` Dave Page <[email protected]>
2019-07-11 10:19 ` Dave Page <[email protected]>
2019-07-11 18:39 ` Ganesh Jaybhay <[email protected]>
2019-07-12 09:06 ` Dave Page <[email protected]>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox