Allow screen-reader to read label & description of non-textable elements. Fixes #4762.

Allow screen-reader to identify the alert errors. Fixes #4763

  Added role alertdialog for confirm and alert dialog.
  Added role status for all status bars/banners.
  Added role alert for error bars.
  Added aria-labelledby for charts on each dashboard.
  Added tabindex for each chart so that it is navigable using tab key.
This commit is contained in:
Nagesh Dhope
2020-01-28 11:32:11 +05:30
committed by Akshay Joshi
parent 6594481992
commit f167d77b61
15 changed files with 66 additions and 41 deletions
+2
View File
@@ -11,6 +11,8 @@ New features
| `Issue #2554 <https://redmine.postgresql.org/issues/2554>`_ - Added support for a multi-level partitioned table. | `Issue #2554 <https://redmine.postgresql.org/issues/2554>`_ - Added support for a multi-level partitioned table.
| `Issue #3452 <https://redmine.postgresql.org/issues/3452>`_ - Added a Schema Diff tool to compare two schemas and generate a diff script. | `Issue #3452 <https://redmine.postgresql.org/issues/3452>`_ - Added a Schema Diff tool to compare two schemas and generate a diff script.
| `Issue #4762 <https://redmine.postgresql.org/issues/4762>`_ - Allow screen-reader to read label & description of non-textable elements.
| `Issue #4763 <https://redmine.postgresql.org/issues/4763>`_ - Allow screen-reader to identify the alert errors.
Housekeeping Housekeeping
************ ************
@@ -24,7 +24,7 @@
<div class="pr-2"> <div class="pr-2">
<i class="fa fa-exclamation-triangle text-danger" aria-hidden="true"></i> <i class="fa fa-exclamation-triangle text-danger" aria-hidden="true"></i>
</div> </div>
<div class="alert-text" role="status">{{ errmsg }}</div> <div class="alert-text" role="alert">{{ errmsg }}</div>
</div> </div>
</div> </div>
</div> </div>
@@ -44,7 +44,7 @@
<div class="pr-2"> <div class="pr-2">
<i class="fa fa-exclamation-triangle text-danger" aria-hidden="true"></i> <i class="fa fa-exclamation-triangle text-danger" aria-hidden="true"></i>
</div> </div>
<div class="alert-text" role="status">{{ errmsg }}</div> <div class="alert-text" role="alert">{{ errmsg }}</div>
</div> </div>
</div> </div>
</div> </div>
+4 -4
View File
@@ -201,7 +201,7 @@ define('pgadmin.browser', [
isCloseable: false, isCloseable: false,
isPrivate: true, isPrivate: true,
elContainer: true, elContainer: true,
content: '<div class="obj_properties container-fluid"><div class="alert alert-info pg-panel-message">' + select_object_msg + '</div></div>', content: '<div class="obj_properties container-fluid"><div role="status" class="alert alert-info pg-panel-message">' + select_object_msg + '</div></div>',
events: panelEvents, events: panelEvents,
onCreate: function(myPanel, $container) { onCreate: function(myPanel, $container) {
$container.addClass('pg-no-overflow'); $container.addClass('pg-no-overflow');
@@ -215,7 +215,7 @@ define('pgadmin.browser', [
width: 500, width: 500,
isCloseable: false, isCloseable: false,
isPrivate: true, isPrivate: true,
content: '<div class="negative-space p-2"><div class="alert alert-info pg-panel-message pg-panel-statistics-message">' + select_object_msg + '</div><div class="pg-panel-statistics-container d-none"></div></div>', content: '<div class="negative-space p-2"><div role="status" class="alert alert-info pg-panel-message pg-panel-statistics-message">' + select_object_msg + '</div><div class="pg-panel-statistics-container d-none"></div></div>',
events: panelEvents, events: panelEvents,
}), }),
// Reversed engineered SQL for the object // Reversed engineered SQL for the object
@@ -236,7 +236,7 @@ define('pgadmin.browser', [
width: 500, width: 500,
isCloseable: false, isCloseable: false,
isPrivate: true, isPrivate: true,
content: '<div class="negative-space p-2"><div class="alert alert-info pg-panel-message pg-panel-depends-message">' + select_object_msg + '</div><div class="pg-panel-dependencies-container d-none"></div></div>', content: '<div class="negative-space p-2"><div role="status" class="alert alert-info pg-panel-message pg-panel-depends-message">' + select_object_msg + '</div><div class="pg-panel-dependencies-container d-none"></div></div>',
events: panelEvents, events: panelEvents,
}), }),
// Dependents of the object // Dependents of the object
@@ -247,7 +247,7 @@ define('pgadmin.browser', [
width: 500, width: 500,
isCloseable: false, isCloseable: false,
isPrivate: true, isPrivate: true,
content: '<div class="negative-space p-2"><div class="alert alert-info pg-panel-message pg-panel-depends-message">' + select_object_msg + '</div><div class="pg-panel-dependents-container d-none"></div></div>', content: '<div class="negative-space p-2"><div role="status" class="alert alert-info pg-panel-message pg-panel-depends-message">' + select_object_msg + '</div><div class="pg-panel-dependents-container d-none"></div></div>',
events: panelEvents, events: panelEvents,
}), }),
}, },
+1 -1
View File
@@ -216,7 +216,7 @@ define([
j.empty(); j.empty();
j.data('obj-view', gridView); j.data('obj-view', gridView);
$msgContainer = '<div class="alert alert-info pg-panel-message pg-panel-properties-message">' + $msgContainer = '<div role="status" class="alert alert-info pg-panel-message pg-panel-properties-message">' +
gettext('Retrieving data from the server...') + '</div>'; gettext('Retrieving data from the server...') + '</div>';
$msgContainer = $($msgContainer).appendTo(j); $msgContainer = $($msgContainer).appendTo(j);
+3 -3
View File
@@ -329,7 +329,7 @@ define('pgadmin.browser.node', [
<div class="pr-2"> <div class="pr-2">
<i class="fa fa-exclamation-triangle text-danger" aria-hidden="true" role="img"></i> <i class="fa fa-exclamation-triangle text-danger" aria-hidden="true" role="img"></i>
</div> </div>
<div class="alert-text">${msg}</div> <div role="alert" class="alert-text">${msg}</div>
<div class="ml-auto close-error-bar"> <div class="ml-auto close-error-bar">
<a class="close-error fa fa-times text-danger"></a> <a class="close-error fa fa-times text-danger"></a>
</div> </div>
@@ -396,7 +396,7 @@ define('pgadmin.browser.node', [
if (!newModel.isNew()) { if (!newModel.isNew()) {
// This is definetely not in create mode // This is definetely not in create mode
var msgDiv = '<div class="alert alert-info pg-panel-message pg-panel-properties-message">' + var msgDiv = '<div role="status" class="alert alert-info pg-panel-message pg-panel-properties-message">' +
gettext('Retrieving data from the server...') + '</div>', gettext('Retrieving data from the server...') + '</div>',
$msgDiv = $(msgDiv); $msgDiv = $(msgDiv);
var timer = setTimeout(function(ctx) { var timer = setTimeout(function(ctx) {
@@ -500,7 +500,7 @@ define('pgadmin.browser.node', [
isPrivate: true, isPrivate: true,
isLayoutMember: false, isLayoutMember: false,
elContainer: true, elContainer: true,
content: '<div class="obj_properties container-fluid"><div class="alert alert-info pg-panel-message">' + gettext('Please wait while we fetch information about the node from the server...') + '</div></div>', content: '<div class="obj_properties container-fluid"><div role="status" class="alert alert-info pg-panel-message">' + gettext('Please wait while we fetch information about the node from the server...') + '</div></div>',
onCreate: function(myPanel, $container) { onCreate: function(myPanel, $container) {
$container.addClass('pg-no-overflow'); $container.addClass('pg-no-overflow');
}, },
+2 -2
View File
@@ -106,7 +106,7 @@ define([
' </div>' + ' </div>' +
' <% } %>' + ' <% } %>' +
' <div class="wizard-progress-bar"><% if (show_progress_bar) { %>' + ' <div class="wizard-progress-bar"><% if (show_progress_bar) { %>' +
' <p class="alert alert-info col-sm-12"><%= show_progress_bar %></p><% } %>' + ' <p role="status" class="alert alert-info col-sm-12"><%= show_progress_bar %></p><% } %>' +
' </div>' + ' </div>' +
' <div class="wizard-right-panel_content">' + ' <div class="wizard-right-panel_content">' +
' </div>' + ' </div>' +
@@ -119,7 +119,7 @@ define([
' <div class="pr-2"> ' + ' <div class="pr-2"> ' +
' <i class="fa fa-exclamation-triangle text-danger" aria-hidden="true" role="img"></i> ' + ' <i class="fa fa-exclamation-triangle text-danger" aria-hidden="true" role="img"></i> ' +
' </div> ' + ' </div> ' +
' <div class="alert-text"></div> ' + ' <div role="alert" class="alert-text"></div> ' +
' <div class="ml-auto close-error-bar"> ' + ' <div class="ml-auto close-error-bar"> ' +
' <a aria-label="' + gettext('Close error bar') + '" class="close-error fa fa-times text-danger"></a> ' + ' <a aria-label="' + gettext('Close error bar') + '" class="close-error fa fa-times text-danger"></a> ' +
' </div> ' + ' </div> ' +
@@ -2,8 +2,8 @@
<div id="dashboard-graphs" class="dashboard-hidden"> <div id="dashboard-graphs" class="dashboard-hidden">
<div class="row dashboard-row"> <div class="row dashboard-row">
<div class="col-md-6 col-12"> <div class="col-md-6 col-12">
<div class="card"> <div class="card" role="object-document" tabindex="0" aria-labelledby="database-session-graph">
<div class="card-header"> <div class="card-header" id="database-session-graph">
{{ _('Database sessions') }} {{ _('Database sessions') }}
</div> </div>
<div class="card-body dashboard-graph-body"> <div class="card-body dashboard-graph-body">
@@ -12,8 +12,8 @@
</div> </div>
</div> </div>
<div class="col-md-6 col-12"> <div class="col-md-6 col-12">
<div class="card"> <div class="card" role="object-document" tabindex="0" aria-labelledby="transactions-per-second-graph">
<div class="card-header"> <div class="card-header" id="transactions-per-second-graph">
{{ _('Transactions per second') }} {{ _('Transactions per second') }}
</div> </div>
<div class="card-body dashboard-graph-body"> <div class="card-body dashboard-graph-body">
@@ -24,8 +24,8 @@
</div> </div>
<div class="row dashboard-row"> <div class="row dashboard-row">
<div class="col-md-4 col-12"> <div class="col-md-4 col-12">
<div class="card"> <div class="card" role="object-document" tabindex="0" aria-labelledby="tuples-in-graph">
<div class="card-header"> <div class="card-header" id="tuples-in-graph">
{{ _('Tuples in') }} {{ _('Tuples in') }}
</div> </div>
<div class="card-body dashboard-graph-body"> <div class="card-body dashboard-graph-body">
@@ -34,8 +34,8 @@
</div> </div>
</div> </div>
<div class="col-md-4 col-12"> <div class="col-md-4 col-12">
<div class="card"> <div class="card" role="object-document" tabindex="0" aria-labelledby="tuples-out-graph">
<div class="card-header"> <div class="card-header" id="tuples-out-graph">
{{ _('Tuples out') }} {{ _('Tuples out') }}
</div> </div>
<div class="card-body dashboard-graph-body"> <div class="card-body dashboard-graph-body">
@@ -44,8 +44,8 @@
</div> </div>
</div> </div>
<div class="col-md-4 col-12"> <div class="col-md-4 col-12">
<div class="card"> <div class="card" role="object-document" tabindex="0" aria-labelledby="block-io-graph">
<div class="card-header"> <div class="card-header" id="block-io-graph">
{{ _('Block I/O') }} {{ _('Block I/O') }}
</div> </div>
<div class="card-body dashboard-graph-body"> <div class="card-body dashboard-graph-body">
@@ -2,8 +2,8 @@
<div id="dashboard-graphs" class="dashboard-hidden"> <div id="dashboard-graphs" class="dashboard-hidden">
<div class="row dashboard-row"> <div class="row dashboard-row">
<div class="col-md-6 col-12"> <div class="col-md-6 col-12">
<div class="card"> <div class="card" role="object-document" tabindex="0" aria-labelledby="server-sessions-graph">
<div class="card-header"> <div class="card-header" id="server-sessions-graph">
{{ _('Server sessions') }} {{ _('Server sessions') }}
</div> </div>
<div class="card-body dashboard-graph-body"> <div class="card-body dashboard-graph-body">
@@ -12,8 +12,8 @@
</div> </div>
</div> </div>
<div class="col-md-6 col-12"> <div class="col-md-6 col-12">
<div class="card"> <div class="card" role="object-document" tabindex="0" aria-labelledby="transactions-per-second-graph">
<div class="card-header"> <div class="card-header" id="transactions-per-second-graph">
{{ _('Transactions per second') }} {{ _('Transactions per second') }}
</div> </div>
<div class="card-body dashboard-graph-body"> <div class="card-body dashboard-graph-body">
@@ -24,8 +24,8 @@
</div> </div>
<div class="row dashboard-row"> <div class="row dashboard-row">
<div class="col-md-4 col-12"> <div class="col-md-4 col-12">
<div class="card"> <div class="card" role="object-document" tabindex="0" aria-labelledby="tuples-in-graph">
<div class="card-header"> <div class="card-header" id="tuples-in-graph">
{{ _('Tuples in') }} {{ _('Tuples in') }}
</div> </div>
<div class="card-body dashboard-graph-body"> <div class="card-body dashboard-graph-body">
@@ -34,8 +34,8 @@
</div> </div>
</div> </div>
<div class="col-md-4 col-12"> <div class="col-md-4 col-12">
<div class="card"> <div class="card" role="object-document" tabindex="0" aria-labelledby="tuples-out-graph">
<div class="card-header"> <div class="card-header" id="tuples-out-graph">
{{ _('Tuples out') }} {{ _('Tuples out') }}
</div> </div>
<div class="card-body dashboard-graph-body"> <div class="card-body dashboard-graph-body">
@@ -44,8 +44,8 @@
</div> </div>
</div> </div>
<div class="col-md-4 col-12"> <div class="col-md-4 col-12">
<div class="card"> <div class="card" role="object-document" tabindex="0" aria-labelledby="block-o-graph">
<div class="card-header"> <div class="card-header" id="block-o-graph">
{{ _('Block I/O') }} {{ _('Block I/O') }}
</div> </div>
<div class="card-body dashboard-graph-body"> <div class="card-body dashboard-graph-body">
@@ -127,8 +127,8 @@ define([
alertMessage = '\ alertMessage = '\
<div class="media text-danger text-14">\ <div class="media text-danger text-14">\
<div class="media-body media-middle">\ <div class="media-body media-middle">\
<div class="alert-text" role="status">' + promptmsg + '</div><br/>\ <div class="alert-text" role="alert">' + promptmsg + '</div><br/>\
<div class="alert-text">' + gettext('Click for details.') + '</div>\ <div class="alert-text" role="alert">' + gettext('Click for details.') + '</div>\
</div>\ </div>\
</div>'; </div>';
} }
@@ -172,8 +172,8 @@ define([
var alertMessage = '\ var alertMessage = '\
<div class="media text-danger text-14">\ <div class="media text-danger text-14">\
<div class="media-body media-middle">\ <div class="media-body media-middle">\
<div class="alert-text" role="status">' + gettext('INTERNAL SERVER ERROR') + '</div><br/>\ <div class="alert-text" role="alert">' + gettext('INTERNAL SERVER ERROR') + '</div><br/>\
<div class="alert-text">' + gettext('Click for details.') + '</div>\ <div class="alert-text" role="alert">' + gettext('Click for details.') + '</div>\
</div>\ </div>\
</div>'; </div>';
@@ -457,6 +457,14 @@ define([
$(this.elements.commands.close).attr('title', gettext('Close')); $(this.elements.commands.close).attr('title', gettext('Close'));
$(this.elements.commands.maximize).attr('title', gettext('Maximize')); $(this.elements.commands.maximize).attr('title', gettext('Maximize'));
$(this.elements.content).addClass('ajs-wrap-text'); $(this.elements.content).addClass('ajs-wrap-text');
$(this.elements.header).attr('id', 'confirm-dialog-header');
$(this.elements.body).attr('id', 'confirm-dialog-body');
$(this.elements.dialog).attr({
role: 'alertdialog',
'aria-modal': 'true',
'aria-labelledby': 'confirm-dialog-header',
'aria-describedby': 'confirm-dialog-body',
});
}, },
reverseButtons: true, reverseButtons: true,
}); });
@@ -465,6 +473,19 @@ define([
reverseButtons: true, reverseButtons: true,
}); });
alertify.alert().set({
onshow:function() {
$(this.elements.header).attr('id', 'alert-dialog-header');
$(this.elements.body).attr('id', 'alert-dialog-body');
$(this.elements.modal).attr({
role: 'alertdialog',
'aria-modal': 'true',
'aria-labelledby': 'alert-dialog-header',
'aria-describedby': 'alert-dialog-body',
});
},
});
/* Suppress the enter key events occurring from select2 boxes /* Suppress the enter key events occurring from select2 boxes
* so that the dialog does not close. * so that the dialog does not close.
* Alertify listens to keyup events on the body element unfortunately * Alertify listens to keyup events on the body element unfortunately
@@ -129,7 +129,7 @@ let FilterDialog = {
' <div class="pr-2"> ' + ' <div class="pr-2"> ' +
' <i class="fa fa-exclamation-triangle text-danger" aria-hidden="true"></i> ' + ' <i class="fa fa-exclamation-triangle text-danger" aria-hidden="true"></i> ' +
' </div> ' + ' </div> ' +
' <div class="alert-text" role="status"></div> ' + ' <div class="alert-text" role="alert"></div> ' +
' </div> ' + ' </div> ' +
' </div> ' + ' </div> ' +
'</div>').appendTo($container); '</div>').appendTo($container);
@@ -59,7 +59,7 @@ export default class QueryHistory {
this.parentNode.empty() this.parentNode.empty()
.removeClass('d-flex') .removeClass('d-flex')
.append( .append(
`<div class='alert alert-info pg-panel-message'>${gettext( `<div role="status" class='alert alert-info pg-panel-message'>${gettext(
'No history found' 'No history found'
)}</div>` )}</div>`
); );
@@ -364,6 +364,7 @@
<div class="connection_status_wrapper d-flex"> <div class="connection_status_wrapper d-flex">
<div id="btn-conn-status" <div id="btn-conn-status"
role="status"
class="connection_status d-flex justify-content-center align-items-center" data-container="body" class="connection_status d-flex justify-content-center align-items-center" data-container="body"
data-toggle="popover" data-placement="bottom" data-toggle="popover" data-placement="bottom"
data-content="" data-content=""
@@ -1726,12 +1726,13 @@ define([
// Create the messages panel to display the message returned from the database server // Create the messages panel to display the message returned from the database server
var messages = new pgAdmin.Browser.Panel({ var messages = new pgAdmin.Browser.Panel({
name: 'messages', name: 'messages',
title: gettext('Messages'), title:
gettext('Messages'),
width: '100%', width: '100%',
height: '100%', height: '100%',
isCloseable: false, isCloseable: false,
isPrivate: true, isPrivate: true,
content: '<div id="messages" class="messages" tabindex="0"></div>', content: '<div role="status" id="messages" class="messages" tabindex="0"></div>',
}); });
// Create the result panel to display the result after debugging the function // Create the result panel to display the result after debugging the function
@@ -262,7 +262,7 @@ define('tools.querytool', [
height: '100%', height: '100%',
isCloseable: false, isCloseable: false,
isPrivate: true, isPrivate: true,
content: '<div class="sql-editor-message" tabindex="0"></div>', content: '<div role="status" class="sql-editor-message" tabindex="0"></div>',
}); });
var history = new pgAdmin.Browser.Panel({ var history = new pgAdmin.Browser.Panel({