1) Allow screen-reader to read relationship attributes for tab, tabpanels and tables under it. Similar changes are done for subnode controls.

2) Add role="img" for font icons.

Fixes #4764
This commit is contained in:
Aditya Toshniwal
2019-12-17 13:22:36 +05:30
committed by Akshay Joshi
parent e29ea15554
commit f1a18749f6
16 changed files with 92 additions and 75 deletions

View File

@@ -9,6 +9,7 @@ This release contains a number of bug fixes and new features since the release o
New features New features
************ ************
| `Issue #4764 <https://redmine.postgresql.org/issues/4764>`_ - Allow screen-reader to read relationship attributes in nested elements.
Housekeeping Housekeeping
************ ************

View File

@@ -353,7 +353,7 @@ define(['sources/gettext', 'underscore', 'jquery', 'backbone', 'backform',
this.$el.attr('target', this.elId); this.$el.attr('target', this.elId);
var collection = this.model.get(this.column.get('name')), var collection = this.model.get(this.column.get('name')),
tbl = $('<table></table>').appendTo(this.$el), tbl = $('<table aria-label='+this.column.get('label')+'></table>').appendTo(this.$el),
self = this, self = this,
privilege = true, with_grant = true; privilege = true, with_grant = true;

View File

@@ -43,7 +43,7 @@ define('pgadmin.node.server', [
if (_.isUndefined(this.get('label')) || if (_.isUndefined(this.get('label')) ||
_.isNull(this.get('label')) || _.isNull(this.get('label')) ||
String(this.get('label')).replace(/^\s+|\s+$/g, '') == '') { String(this.get('label')).replace(/^\s+|\s+$/g, '') == '') {
var errmsg = gettext('Label must be specified.'); var errmsg = gettext('Security label must be specified.');
this.errorModel.set('label', errmsg); this.errorModel.set('label', errmsg);
return errmsg; return errmsg;
} }

View File

@@ -99,7 +99,7 @@ define([
'<button tabindex="0" type="<%= type %>" ', '<button tabindex="0" type="<%= type %>" ',
'class="btn <%=extraClasses.join(\' \')%>"', 'class="btn <%=extraClasses.join(\' \')%>"',
'<% if (disabled) { %> disabled="disabled"<% } %> title="<%-tooltip%>">', '<% if (disabled) { %> disabled="disabled"<% } %> title="<%-tooltip%>">',
'<span class="<%= icon %>"></span><% if (label != "") { %>&nbsp;<%-label%><% } %></button>', '<span class="<%= icon %>" role="img"></span><% if (label != "") { %>&nbsp;<%-label%><% } %></button>',
].join(' ')); ].join(' '));
if (location == 'header') { if (location == 'header') {
btnGroup.appendTo(that.header); btnGroup.appendTo(that.header);

View File

@@ -327,7 +327,7 @@ define('pgadmin.browser.node', [
<div class="error-in-footer"> <div class="error-in-footer">
<div class="d-flex px-2 py-1"> <div class="d-flex px-2 py-1">
<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" role="img"></i>
</div> </div>
<div class="alert-text">${msg}</div> <div class="alert-text">${msg}</div>
<div class="ml-auto close-error-bar"> <div class="ml-auto close-error-bar">

View File

@@ -32,7 +32,7 @@ define([
let $selectAll = $([ let $selectAll = $([
'<button class="btn btn-secondary btn-sm" type="button"', '<button class="btn btn-secondary btn-sm" type="button"',
' style="width: 49%;margin: 0 0.5%;">', ' style="width: 49%;margin: 0 0.5%;">',
'<i class="fa fa-check-square-o"></i>', '<i class="fa fa-check-square-o" role="img"></i>',
'<span style="padding: 0px 5px;">', '<span style="padding: 0px 5px;">',
gettext('Select All'), gettext('Select All'),
'</span></button>', '</span></button>',
@@ -41,7 +41,7 @@ define([
let $unselectAll = $([ let $unselectAll = $([
'<button class="btn btn-secondary btn-sm" type="button"', '<button class="btn btn-secondary btn-sm" type="button"',
' style="width: 49%;margin: 0 0.5%;">', ' style="width: 49%;margin: 0 0.5%;">',
'<i class="fa fa-square-o"></i><span style="padding: 0px 5px;">', '<i class="fa fa-square-o"></i><span style="padding: 0px 5px;" role="img">',
gettext('Unselect All'), gettext('Unselect All'),
'</span></button>', '</span></button>',
].join('')); ].join(''));

View File

@@ -117,7 +117,7 @@ define([
' <div class="error-in-footer"> ' + ' <div class="error-in-footer"> ' +
' <div class="d-flex px-2 py-1"> ' + ' <div class="d-flex px-2 py-1"> ' +
' <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" role="img"></i> ' +
' </div> ' + ' </div> ' +
' <div class="alert-text"></div> ' + ' <div class="alert-text"></div> ' +
' <div class="ml-auto close-error-bar"> ' + ' <div class="ml-auto close-error-bar"> ' +
@@ -130,18 +130,18 @@ define([
' <div>' + ' <div>' +
' <button title = "' + gettext('Help for this dialog.') + '"' + ' <button title = "' + gettext('Help for this dialog.') + '"' +
' class="btn btn-secondary pull-left wizard-help" <%=this.options.wizard_help ? "" : "disabled" %>>' + ' class="btn btn-secondary pull-left wizard-help" <%=this.options.wizard_help ? "" : "disabled" %>>' +
' <span class="fa fa-lg fa-question"></span></button>' + ' <span class="fa fa-lg fa-question" role="img"></span></button>' +
' </div>' + ' </div>' +
' <div class="ml-auto">' + ' <div class="ml-auto">' +
' <button class="btn btn-secondary wizard-cancel" <%=this.options.disable_cancel ? "disabled" : ""%>>' + ' <button class="btn btn-secondary wizard-cancel" <%=this.options.disable_cancel ? "disabled" : ""%>>' +
' <i class="fa fa-close"></i>&nbsp;' + gettext('Cancel') + '</button>' + ' <i class="fa fa-close" role="img"></i>&nbsp;' + gettext('Cancel') + '</button>' +
' <button class="btn btn-secondary wizard-back" <%=this.options.disable_prev ? "disabled" : ""%>>' + ' <button class="btn btn-secondary wizard-back" <%=this.options.disable_prev ? "disabled" : ""%>>' +
' <i class="fa fa-backward"></i>&nbsp;' + gettext('Back') + '</button>' + ' <i class="fa fa-backward" role="img"></i>&nbsp;' + gettext('Back') + '</button>' +
' <button class="btn btn-secondary wizard-next" <%=this.options.disable_next ? "disabled" : ""%>>' + ' <button class="btn btn-secondary wizard-next" <%=this.options.disable_next ? "disabled" : ""%>>' +
' ' + gettext('Next') + ' ' + gettext('Next') +
' &nbsp;<i class="fa fa-forward"></i></button>' + ' &nbsp;<i class="fa fa-forward"></i></button>' +
' <button class="btn btn-primary wizard-finish" <%=this.options.disable_finish ? "disabled" : ""%>>' + ' <button class="btn btn-primary wizard-finish" <%=this.options.disable_finish ? "disabled" : ""%>>' +
' <i class="fa fa-check"></i>&nbsp;' + gettext('Finish') + '</button>' + ' <i class="fa fa-check" role="img"></i>&nbsp;' + gettext('Finish') + '</button>' +
' </div>' + ' </div>' +
' </div>' + ' </div>' +
' </div>' + ' </div>' +

View File

@@ -57,22 +57,22 @@
</div> </div>
<div id="dashboard-activity" class="card dashboard-row dashboard-hidden"> <div id="dashboard-activity" class="card dashboard-row dashboard-hidden">
<div class="card-header"> <div class="card-header">
{{ _('Server activity') }} <span id="dashboard-activity-header">{{ _('Server activity') }}</span>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="row"> <div class="row">
<div class="col-md-9 col-12 pr-0"> <div class="col-md-9 col-12 pr-0">
<ul class="nav nav-tabs" role="tablist"> <ul class="nav nav-tabs" role="tablist" aria-labelledby="dashboard-activity-header">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link active show" href="#tab_panel_database_activity" aria-controls="tab_database_activity" <a class="nav-link active show" id="tab_panel_database_activity_tab" href="#tab_panel_database_activity" aria-controls="tab_database_activity"
role="tab" data-toggle="tab">{{ _('Sessions') }}</a> role="tab" data-toggle="tab">{{ _('Sessions') }}</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="#tab_panel_database_locks" aria-controls="tab_database_locks" <a class="nav-link" id="tab_panel_database_locks_tab" href="#tab_panel_database_locks" aria-controls="tab_database_locks"
role="tab" data-toggle="tab">{{ _('Locks') }}</a> role="tab" data-toggle="tab">{{ _('Locks') }}</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="#tab_panel_database_prepared" aria-controls="tab_database_prepared" <a class="nav-link" id="tab_panel_database_prepared_tab" href="#tab_panel_database_prepared" aria-controls="tab_database_prepared"
role="tab" data-toggle="tab">{{ _('Prepared Transactions') }}</a> role="tab" data-toggle="tab">{{ _('Prepared Transactions') }}</a>
</li> </li>
</ul> </ul>
@@ -96,13 +96,13 @@
<!-- Tab panes --> <!-- Tab panes -->
<div class="tab-content"> <div class="tab-content">
<div role="tabpanel" class="tab-pane negative-space p-2 active show" id="tab_panel_database_activity"> <div role="tabpanel" class="tab-pane negative-space p-2 active show" id="tab_panel_database_activity" aria-labelledby="tab_panel_database_activity_tab">
<div id="database_activity" class="grid-container"></div> <div id="database_activity" class="grid-container"></div>
</div> </div>
<div role="tabpanel" class="tab-pane negative-space p-2" id="tab_panel_database_locks"> <div role="tabpanel" class="tab-pane negative-space p-2" id="tab_panel_database_locks" aria-labelledby="tab_panel_database_locks_tab">
<div id="database_locks" class="grid-container"></div> <div id="database_locks" class="grid-container"></div>
</div> </div>
<div role="tabpanel" class="tab-pane negative-space p-2" id="tab_panel_database_prepared"> <div role="tabpanel" class="tab-pane negative-space p-2" id="tab_panel_database_prepared" aria-labelledby="tab_panel_database_prepared_tab">
<div id="database_prepared" class="grid-container"></div> <div id="database_prepared" class="grid-container"></div>
</div> </div>
</div> </div>

View File

@@ -57,26 +57,26 @@
</div> </div>
<div id="dashboard-activity" class="card dashboard-row dashboard-hidden"> <div id="dashboard-activity" class="card dashboard-row dashboard-hidden">
<div class="card-header"> <div class="card-header">
{{ _('Server activity') }} <span id="server-activity-header">{{ _('Server activity') }}</span>
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="row"> <div class="row">
<div class="col-md-9 col-12 pr-0"> <div class="col-md-9 col-12 pr-0">
<ul class="nav nav-tabs" role="tablist"> <ul class="nav nav-tabs" role="tablist" aria-labelledby="server-activity-header">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link active show" href="#tab_panel_server_activity" aria-controls="tab_server_activity" <a class="nav-link active show" id="tab_panel_server_activity_tab" href="#tab_panel_server_activity" aria-controls="tab_server_activity"
role="tab" data-toggle="tab">{{_('Sessions') }}</a> role="tab" data-toggle="tab">{{_('Sessions') }}</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="#tab_panel_server_locks" aria-controls="tab_server_locks" <a class="nav-link" id="tab_panel_server_locks_tab" href="#tab_panel_server_locks" aria-controls="tab_server_locks"
role="tab" data-toggle="tab">{{ _('Locks') }}</a> role="tab" data-toggle="tab">{{ _('Locks') }}</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="#tab_panel_server_prepared" aria-controls="tab_server_prepared" <a class="nav-link" id="tab_panel_server_prepared_tab" href="#tab_panel_server_prepared" aria-controls="tab_server_prepared"
role="tab" data-toggle="tab">{{ _('Prepared Transactions') }}</a> role="tab" data-toggle="tab">{{ _('Prepared Transactions') }}</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="#tab_panel_server_config" aria-controls="tab_server_config" <a class="nav-link" id="tab_panel_server_config_tab" href="#tab_panel_server_config" aria-controls="tab_server_config"
role="tab" data-toggle="tab">{{ _('Configuration') }}</a> role="tab" data-toggle="tab">{{ _('Configuration') }}</a>
</li> </li>
</ul> </ul>
@@ -100,16 +100,16 @@
<!-- Tab panes --> <!-- Tab panes -->
<div class="tab-content"> <div class="tab-content">
<div role="tabpanel" class="tab-pane negative-space p-2 active show" id="tab_panel_server_activity"> <div role="tabpanel" class="tab-pane negative-space p-2 active show" id="tab_panel_server_activity" aria-labelledby="tab_panel_server_activity_tab">
<div id="server_activity" class="grid-container"></div> <div id="server_activity" class="grid-container"></div>
</div> </div>
<div role="tabpanel" class="tab-pane negative-space p-2" id="tab_panel_server_locks"> <div role="tabpanel" class="tab-pane negative-space p-2" id="tab_panel_server_locks" aria-labelledby="tab_panel_server_locks_tab">
<div id="server_locks" class="grid-container"></div> <div id="server_locks" class="grid-container"></div>
</div> </div>
<div role="tabpanel" class="tab-pane negative-space p-2" id="tab_panel_server_prepared"> <div role="tabpanel" class="tab-pane negative-space p-2" id="tab_panel_server_prepared" aria-labelledby="tab_panel_server_prepared_tab">
<div id="server_prepared" class="grid-container"></div> <div id="server_prepared" class="grid-container"></div>
</div> </div>
<div role="tabpanel" class="tab-pane negative-space p-2" id="tab_panel_server_config"> <div role="tabpanel" class="tab-pane negative-space p-2" id="tab_panel_server_config" aria-labelledby="tab_panel_server_config_tab">
<div id="server_config" class="grid-container"></div> <div id="server_config" class="grid-container"></div>
</div> </div>
</div> </div>

View File

@@ -36,21 +36,21 @@ define('misc.bgprocess', [
success_status_tpl: _.template(` success_status_tpl: _.template(`
<div class="d-flex px-2 py-1 bg-success-light border border-success rounded"> <div class="d-flex px-2 py-1 bg-success-light border border-success rounded">
<div class="pr-2"> <div class="pr-2">
<i class="fa fa-check fa-lg text-success pg-bg-status-icon" aria-hidden="true"></i> <i class="fa fa-check fa-lg text-success pg-bg-status-icon" aria-hidden="true" role="img"></i>
</div> </div>
<div class="text-body mx-auto pg-bg-status-text"><%-status_text%></div> <div class="text-body mx-auto pg-bg-status-text"><%-status_text%></div>
</div>`), </div>`),
failed_status_tpl: _.template(` failed_status_tpl: _.template(`
<div class="d-flex px-2 py-1 bg-danger-lighter border border-danger rounded"> <div class="d-flex px-2 py-1 bg-danger-lighter border border-danger rounded">
<div class="pr-2"> <div class="pr-2">
<i class="fa fa-close fa-lg text-danger pg-bg-status-icon" aria-hidden="true"></i> <i class="fa fa-close fa-lg text-danger pg-bg-status-icon" aria-hidden="true" role="img"></i>
</div> </div>
<div class="text-body mx-auto pg-bg-status-text"><%-status_text%></div> <div class="text-body mx-auto pg-bg-status-text"><%-status_text%></div>
</div>`), </div>`),
other_status_tpl: _.template(` other_status_tpl: _.template(`
<div class="d-flex px-2 py-1 bg-primary-light border border-primary rounded"> <div class="d-flex px-2 py-1 bg-primary-light border border-primary rounded">
<div class="pr-2"> <div class="pr-2">
<i class="fa fa-info fa-lg text-primary pg-bg-status-icon" aria-hidden="true"></i> <i class="fa fa-info fa-lg text-primary pg-bg-status-icon" aria-hidden="true" role="img"></i>
</div> </div>
<div class="text-body mx-auto pg-bg-status-text"><%-status_text%></div> <div class="text-body mx-auto pg-bg-status-text"><%-status_text%></div>
</div>`), </div>`),
@@ -299,7 +299,7 @@ define('misc.bgprocess', [
<div class="card-header bg-primary d-flex"> <div class="card-header bg-primary d-flex">
<div>${self.type_desc}</div> <div>${self.type_desc}</div>
<div class="ml-auto"> <div class="ml-auto">
<button class="btn btn-sm-sq btn-primary pg-bg-close"><i class="fa fa-lg fa-close"></i></button> <button class="btn btn-sm-sq btn-primary pg-bg-close"><i class="fa fa-lg fa-close" role="img"></i></button>
</div> </div>
</div> </div>
<div class="card-body px-2"> <div class="card-body px-2">
@@ -307,12 +307,12 @@ define('misc.bgprocess', [
<div class="py-1">${self.stime.toString()}</div> <div class="py-1">${self.stime.toString()}</div>
<div class="d-flex py-1"> <div class="d-flex py-1">
<div class="my-auto mr-2"> <div class="my-auto mr-2">
<span class="fa fa-clock-o fa-2x"></span> <span class="fa fa-clock-o fa-2x" role="img"></span>
</div> </div>
<div class="pg-bg-etime my-auto mr-2"></div> <div class="pg-bg-etime my-auto mr-2"></div>
<div class="ml-auto"> <div class="ml-auto">
<button class="btn btn-secondary pg-bg-more-details"><span class="fa fa-info-circle"></span>&nbsp;${gettext('More details...')}</button> <button class="btn btn-secondary pg-bg-more-details"><span class="fa fa-info-circle" role="img"></span>&nbsp;${gettext('More details...')}</button>
<button class="btn btn-danger bg-process-stop"><span class="fa fa-times-circle"></span>&nbsp;${gettext('Stop Process')}</button> <button class="btn btn-danger bg-process-stop"><span class="fa fa-times-circle" role="img"></span>&nbsp;${gettext('Stop Process')}</button>
</div> </div>
</div> </div>
<div class="pg-bg-status py-1"> <div class="pg-bg-status py-1">
@@ -614,14 +614,14 @@ define('misc.bgprocess', [
'<div class="bg-detailed-desc"></div>' + '<div class="bg-detailed-desc"></div>' +
'<div class="bg-process-stats d-flex py-1">' + '<div class="bg-process-stats d-flex py-1">' +
'<div class="my-auto mr-2">' + '<div class="my-auto mr-2">' +
'<span class="fa fa-clock-o fa-2x"></span>' + '<span class="fa fa-clock-o fa-2x" role="img"></span>' +
'</div>' + '</div>' +
'<div class="pg-bg-etime my-auto mr-2">'+ '<div class="pg-bg-etime my-auto mr-2">'+
'<span>' + gettext('Start time') + ': <span class="bgprocess-start-time"></span>' + '<span>' + gettext('Start time') + ': <span class="bgprocess-start-time"></span>' +
'</span>'+ '</span>'+
'</div>' + '</div>' +
'<div class="ml-auto">' + '<div class="ml-auto">' +
'<button type="button" class="btn btn-danger bg-process-stop"><span class="fa fa-times-circle"></span>&nbsp;' + gettext('Stop Process') + '</button>' + '<button type="button" class="btn btn-danger bg-process-stop"><span class="fa fa-times-circle" role="img"></span>&nbsp;' + gettext('Stop Process') + '</button>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'</div>' + '</div>' +

View File

@@ -552,7 +552,7 @@ define([
'"><div class="clip"><span data-alt="' + '"><div class="clip"><span data-alt="' +
file_path_orig + '" class="' + class_type + '"></span>'; file_path_orig + '" class="' + class_type + '"></span>';
if ((data[key]).Protected == 1) { if ((data[key]).Protected == 1) {
result += '<span class="fa fa-lock fm_lock_icon" data-protected="protected"></span>'; result += '<span class="fa fa-lock fm_lock_icon" data-protected="protected" role="img"></span>';
} }
result += '</div>'; result += '</div>';
@@ -632,7 +632,7 @@ define([
let data_protected = ''; let data_protected = '';
if ((data[key]).Protected == 1) { if ((data[key]).Protected == 1) {
data_protected = '<i class="fa fa-lock tbl_lock_icon" data-protected="protected"></i>'; data_protected = '<i class="fa fa-lock tbl_lock_icon" data-protected="protected" role="img"></i>';
} }
if (!has_capability(data[key], 'rename')) { if (!has_capability(data[key], 'rename')) {
result += data_protected; result += data_protected;
@@ -1586,7 +1586,7 @@ define([
// template for creating new folder // template for creating new folder
folder_div = folder_div =
'<li class=\'cap_download cap_delete cap_select_file cap_select_folder cap_rename cap_create cap_upload\'>' + '<li class=\'cap_download cap_delete cap_select_file cap_select_folder cap_rename cap_create cap_upload\'>' +
'<div class=\'clip\'><span data-alt=\'\' class=\'fa fa-folder-open fm_folder_grid\'></span></div>' + '<div class=\'clip\'><span data-alt=\'\' class=\'fa fa-folder-open fm_folder_grid\' role="img"></span></div>' +
'<div><input type=\'text\' class=\'fm_file_rename\'><span class="less_text" title=\'\'>New_Folder</span></div>' + '<div><input type=\'text\' class=\'fm_file_rename\'><span class="less_text" title=\'\'>New_Folder</span></div>' +
'<span class=\'meta size\'></span><span class=\'meta created\'></span><span class=\'meta modified\'></span></li>'; '<span class=\'meta size\'></span><span class=\'meta created\'></span><span class=\'meta modified\'></span></li>';
@@ -1625,7 +1625,7 @@ define([
folder_div = $( folder_div = $(
'<tr class=\'cap_download cap_delete cap_select_file cap_select_folder cap_rename cap_create cap_upload\'>' + '<tr class=\'cap_download cap_delete cap_select_file cap_select_folder cap_rename cap_create cap_upload\'>' +
'<td title=\'\' class=\' tbl_folder\'>' + '<td title=\'\' class=\' tbl_folder\'>' +
'<span class="fa fa-folder-open fm_folder_list"></span>' + '<span class="fa fa-folder-open fm_folder_list" role="img"></span>' +
'<span class="less_text">' + lg.new_folder + '</span>' + '<span class="less_text">' + lg.new_folder + '</span>' +
'<input type=\'text\' class=\'fm_file_rename\'>'+ '<input type=\'text\' class=\'fm_file_rename\'>'+
'</td>'+ '</td>'+

View File

@@ -697,8 +697,8 @@ define([
}, },
template: { template: {
'header': _.template([ 'header': _.template([
'<li class="nav-item" role="presentation" <%=disabled ? "disabled" : ""%>>', '<li class="nav-item" <%=disabled ? "disabled" : ""%>>',
' <a class="nav-link" data-toggle="tab" tabindex="-1" data-tab-index="<%=tabIndex%>" href="#<%=cId%>"', ' <a class="nav-link" data-toggle="tab" role="tab" tabindex="-1" data-tab-index="<%=tabIndex%>" href="#<%=cId%>"',
' id="<%=hId%>" aria-controls="<%=cId%>">', ' id="<%=hId%>" aria-controls="<%=cId%>">',
'<%=label%></a></li>', '<%=label%></a></li>',
].join(' ')), ].join(' ')),
@@ -830,7 +830,7 @@ define([
'header': _.template([ 'header': _.template([
'<div class="<%=Backform.accordianGroupClassName%>" <%=disabled ? "disabled" : ""%>>', '<div class="<%=Backform.accordianGroupClassName%>" <%=disabled ? "disabled" : ""%>>',
' <% if (legend != false) { %>', ' <% if (legend != false) { %>',
' <div class="<%=legendClass%>" <%=collapse ? "data-toggle=\'collapse\'" : ""%> data-target="#<%=cId%>"><%=collapse ? "<span class=\'caret\'></span>" : "" %><%=label%></legend>', ' <div class="<%=legendClass%>" <%=collapse ? "data-toggle=\'collapse\'" : ""%> data-target="#<%=cId%>" aria-controls="<%=cId%>" role="heading" tabindex="0"><%=collapse ? "<span class=\'caret\'></span>" : "" %><%=label%></legend>',
' <% } %>', ' <% } %>',
'</div>', '</div>',
].join('\n')), ].join('\n')),
@@ -1252,10 +1252,11 @@ define([
return this; return this;
}, },
showGridControl: function(data) { showGridControl: function(data) {
data.cId = data.cId || _.uniqueId('pgC_');
var self = this, var self = this,
gridHeader = _.template([ gridHeader = _.template([
'<div class="subnode-header">', '<div class="subnode-header">',
' <label class="control-label pg-el-sm-10"><%-label%></label>', ' <label class="control-label pg-el-sm-10" id="<%=cId%>"><%-label%></label>',
' <button class="btn btn-sm-sq btn-secondary add fa fa-plus" <%=canAdd ? "" : "disabled=\'disabled\'"%> title="' + _('Add new row') + '"><%-add_label%></button>', ' <button class="btn btn-sm-sq btn-secondary add fa fa-plus" <%=canAdd ? "" : "disabled=\'disabled\'"%> title="' + _('Add new row') + '"><%-add_label%></button>',
'</div>', '</div>',
].join('\n')), ].join('\n')),
@@ -1339,6 +1340,9 @@ define([
columns: gridSchema.columns, columns: gridSchema.columns,
collection: collection, collection: collection,
className: 'backgrid table presentation table-bordered table-noouter-border table-hover', className: 'backgrid table presentation table-bordered table-noouter-border table-hover',
attr: {
'aria-labelledby': data.cId,
},
}); });
// Render subNode grid // Render subNode grid

View File

@@ -87,7 +87,9 @@ export class QueryHistoryItem {
let query_source = this.entry.query_source; let query_source = this.entry.query_source;
if(query_source) if(query_source)
this.$el.find('#query_source_icon').addClass(query_source.ICON_CSS_CLASS); this.$el.find('#query_source_icon')
.addClass(query_source.ICON_CSS_CLASS)
.attr('role', 'img');
if(this.entry.is_pgadmin_query) { if(this.entry.is_pgadmin_query) {
this.$el.addClass('pgadmin-query-history-entry'); this.$el.addClass('pgadmin-query-history-entry');

View File

@@ -718,6 +718,7 @@ var InputCellEditor = Backgrid.InputCellEditor = CellEditor.extend({
*/ */
render: function () { render: function () {
var model = this.model; var model = this.model;
this.$el.attr('aria-label', this.column.get("label"));
this.$el.val(this.formatter.fromRaw(model.get(this.column.get("name")), model)); this.$el.val(this.formatter.fromRaw(model.get(this.column.get("name")), model));
return this; return this;
}, },
@@ -2184,6 +2185,7 @@ var HeaderCell = Backgrid.HeaderCell = Backbone.View.extend({
this.$el.append(label); this.$el.append(label);
this.$el.addClass(column.get("name")); this.$el.addClass(column.get("name"));
this.$el.addClass(column.get("direction")); this.$el.addClass(column.get("direction"));
this.$el.attr("role", "columnheader");
this.delegateEvents(); this.delegateEvents();
return this; return this;
} }
@@ -2840,6 +2842,9 @@ var Grid = Backgrid.Grid = Backbone.View.extend({
/** @property */ /** @property */
footer: null, footer: null,
/** @property */
attr: null,
/** /**
Initializes a Grid instance. Initializes a Grid instance.
@@ -2851,6 +2856,7 @@ var Grid = Backgrid.Grid = Backbone.View.extend({
@param {Backgrid.Body} [options.body=Backgrid.Body] An optional Body 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. @param {Backgrid.Row} [options.row=Backgrid.Row] An optional Row class to override the default.
@param {Backgrid.Footer} [options.footer=Backgrid.Footer] An optional Footer class. @param {Backgrid.Footer} [options.footer=Backgrid.Footer] An optional Footer class.
*/ */
initialize: function (options) { initialize: function (options) {
// Convert the list of column objects here first so the subviews don't have // Convert the list of column objects here first so the subviews don't have
@@ -2879,6 +2885,8 @@ var Grid = Backgrid.Grid = Backbone.View.extend({
this.footer = new this.footer(filteredOptions); this.footer = new this.footer(filteredOptions);
} }
this.attr = options.attr || {};
this.listenTo(this.columns, "reset", function () { this.listenTo(this.columns, "reset", function () {
if (this.header) { if (this.header) {
this.header = new (this.header.remove().constructor)(filteredOptions); this.header = new (this.header.remove().constructor)(filteredOptions);
@@ -2960,6 +2968,8 @@ var Grid = Backgrid.Grid = Backbone.View.extend({
} }
this.$el.append(this.body.render().$el); this.$el.append(this.body.render().$el);
this.$el.attr("role", "table");
this.$el.attr(this.attr);
this.delegateEvents(); this.delegateEvents();

View File

@@ -19,13 +19,13 @@
title="" title=""
accesskey="" accesskey=""
tabindex="0"> tabindex="0">
<i class="fa fa-folder-open-o sql-icon-lg" aria-hidden="true"></i> <i class="fa fa-folder-open-o sql-icon-lg" aria-hidden="true" role="img"></i>
</button> </button>
<button id="btn-save-file" type="button" class="btn btn-sm btn-secondary" <button id="btn-save-file" type="button" class="btn btn-sm btn-secondary"
title="" title=""
accesskey="" accesskey=""
disabled> disabled>
<i class="fa fa-floppy-o sql-icon-lg" aria-hidden="true" tabindex="0"></i> <i class="fa fa-floppy-o sql-icon-lg" aria-hidden="true" tabindex="0" role="img"></i>
</button> </button>
<button id="btn-file-menu-dropdown" type="button" class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split" <button id="btn-file-menu-dropdown" type="button" class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" disabled data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" disabled
@@ -49,12 +49,12 @@
title="" title=""
accesskey="" accesskey=""
tabindex="0" disabled> tabindex="0" disabled>
<i class="pg-font-icon icon-save-data-changes sql-icon-lg" aria-hidden="true"></i> <i class="pg-font-icon icon-save-data-changes sql-icon-lg" aria-hidden="true" role="img"></i>
</button> </button>
</div> </div>
<div class="btn-group mr-1" role="group" aria-label=""> <div class="btn-group mr-1" role="group" aria-label="">
<button id="btn-find" type="button" class="btn btn-sm btn-secondary" title="{{ _('Find (Ctrl/Cmd+F)') }}"> <button id="btn-find" type="button" class="btn btn-sm btn-secondary" title="{{ _('Find (Ctrl/Cmd+F)') }}">
<i class="fa fa-search sql-icon-lg" aria-hidden="true" tabindex="0"></i> <i class="fa fa-search sql-icon-lg" aria-hidden="true" tabindex="0" role="img"></i>
</button> </button>
<button id="btn-find-menu-dropdown" type="button" class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split" <button id="btn-find-menu-dropdown" type="button" class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"
@@ -119,7 +119,7 @@
title="" title=""
accesskey="" accesskey=""
tabindex="0" disabled> tabindex="0" disabled>
<i class="fa fa-files-o sql-icon-lg" aria-hidden="true"></i> <i class="fa fa-files-o sql-icon-lg" aria-hidden="true" role="img"></i>
</button> </button>
<button id="btn-copy-row-dropdown" type="button" class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split" <button id="btn-copy-row-dropdown" type="button" class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"
@@ -128,7 +128,7 @@
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li> <li>
<a class="dropdown-item" id="btn-copy-with-header" href="#" tabindex="0"> <a class="dropdown-item" id="btn-copy-with-header" href="#" tabindex="0">
<i class="copy-with-header fa fa-check visibility-hidden" aria-hidden="true"></i> <i class="copy-with-header fa fa-check visibility-hidden" aria-hidden="true" role="img"></i>
<span> {{ _('Copy with headers') }} </span> <span> {{ _('Copy with headers') }} </span>
</a> </a>
</li> </li>
@@ -137,7 +137,7 @@
title="" title=""
accesskey="" accesskey=""
tabindex="0" disabled> tabindex="0" disabled>
<i class="fa fa-clipboard sql-icon-lg" aria-hidden="true"></i> <i class="fa fa-clipboard sql-icon-lg" aria-hidden="true" role="img"></i>
</button> </button>
</div> </div>
<div class="btn-group mr-1" role="group" aria-label=""> <div class="btn-group mr-1" role="group" aria-label="">
@@ -145,14 +145,14 @@
title="" title=""
accesskey="" accesskey=""
tabindex="0" disabled> tabindex="0" disabled>
<i class="fa fa-trash sql-icon-lg" aria-hidden="true"></i> <i class="fa fa-trash sql-icon-lg" aria-hidden="true" role="img"></i>
</button> </button>
</div> </div>
<div class="btn-group mr-1" role="group" aria-label=""> <div class="btn-group mr-1" role="group" aria-label="">
<button id="btn-edit-dropdown" type="button" class="btn btn-sm btn-secondary dropdown-toggle" <button id="btn-edit-dropdown" type="button" class="btn btn-sm btn-secondary dropdown-toggle"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"
title="{{ _('Edit') }}" tabindex="0"> title="{{ _('Edit') }}" tabindex="0">
<i class="fa fa-pencil-square-o sql-icon-lg" aria-hidden="true"></i> <i class="fa fa-pencil-square-o sql-icon-lg" aria-hidden="true" role="img"></i>
</button> </button>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li> <li>
@@ -196,7 +196,7 @@
title="" title=""
accesskey="" accesskey=""
tabindex="0" disabled> tabindex="0" disabled>
<i class="fa fa-filter sql-icon-lg" aria-hidden="true"></i> <i class="fa fa-filter sql-icon-lg" aria-hidden="true" role="img"></i>
</button> </button>
<button id="btn-filter-dropdown" type="button" class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split" <button id="btn-filter-dropdown" type="button" class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"
@@ -236,12 +236,12 @@
title="" title=""
accesskey="" accesskey=""
tabindex="0" disabled > tabindex="0" disabled >
<i class="fa fa-stop sql-icon-lg" aria-hidden="true"></i> <i class="fa fa-stop sql-icon-lg" aria-hidden="true" role="img"></i>
</button> </button>
<button id="btn-flash" data-test-selector="execute-refresh-button" type="button" class="btn btn-sm btn-secondary" style="width: 32px;" <button id="btn-flash" data-test-selector="execute-refresh-button" type="button" class="btn btn-sm btn-secondary" style="width: 32px;"
title="" title=""
tabindex="0" data-click-counter="0" disabled> tabindex="0" data-click-counter="0" disabled>
<i class="fa fa-play sql-icon-lg" aria-hidden="true"></i> <i class="fa fa-play sql-icon-lg" aria-hidden="true" role="img"></i>
</button> </button>
<button id="btn-query-dropdown" type="button" class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split" <button id="btn-query-dropdown" type="button" class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"
@@ -252,13 +252,13 @@
<ul class="dropdown-menu" role="menu"> <ul class="dropdown-menu" role="menu">
<li> <li>
<a class="dropdown-item" id="btn-auto-commit" href="#" tabindex="0"> <a class="dropdown-item" id="btn-auto-commit" href="#" tabindex="0">
<i class="auto-commit fa fa-check visibility-hidden" aria-hidden="true"></i> <i class="auto-commit fa fa-check visibility-hidden" aria-hidden="true" role="img"></i>
<span> {{ _('Auto commit?') }} </span> <span> {{ _('Auto commit?') }} </span>
</a> </a>
</li> </li>
<li> <li>
<a class="dropdown-item" id="btn-auto-rollback" href="#" tabindex="0"> <a class="dropdown-item" id="btn-auto-rollback" href="#" tabindex="0">
<i class="auto-rollback fa fa-check visibility-hidden" aria-hidden="true"></i> <i class="auto-rollback fa fa-check visibility-hidden" aria-hidden="true" role="img"></i>
<span> {{ _('Auto rollback?') }} </span> <span> {{ _('Auto rollback?') }} </span>
</a> </a>
</li> </li>
@@ -269,12 +269,12 @@
title="" title=""
accesskey="" accesskey=""
tabindex="0" disabled> tabindex="0" disabled>
<i class="fa fa-hand-pointer-o sql-icon-lg" aria-hidden="true"></i> <i class="fa fa-hand-pointer-o sql-icon-lg" aria-hidden="true" role="img"></i>
</button> </button>
<button id="btn-explain-analyze" type="button" class="btn btn-sm btn-secondary" <button id="btn-explain-analyze" type="button" class="btn btn-sm btn-secondary"
title="" title=""
accesskey="" disabled> accesskey="" disabled>
<i class="fa fa-list-alt sql-icon-lg" aria-hidden="true"></i> <i class="fa fa-list-alt sql-icon-lg" aria-hidden="true" role="img"></i>
</button> </button>
<button id="btn-explain-options-dropdown" type="button" class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split" <button id="btn-explain-options-dropdown" type="button" class="btn btn-sm btn-secondary dropdown-toggle dropdown-toggle-split"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"
@@ -283,37 +283,37 @@
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li> <li>
<a class="dropdown-item" id="btn-explain-verbose" href="#" tabindex="0"> <a class="dropdown-item" id="btn-explain-verbose" href="#" tabindex="0">
<i class="explain-verbose fa fa-check visibility-hidden" aria-hidden="true"></i> <i class="explain-verbose fa fa-check visibility-hidden" aria-hidden="true" role="img"></i>
<span> {{ _('Verbose') }} </span> <span> {{ _('Verbose') }} </span>
</a> </a>
</li> </li>
<li> <li>
<a class="dropdown-item" id="btn-explain-costs" href="#" tabindex="0"> <a class="dropdown-item" id="btn-explain-costs" href="#" tabindex="0">
<i class="explain-costs fa fa-check visibility-hidden" aria-hidden="true"></i> <i class="explain-costs fa fa-check visibility-hidden" aria-hidden="true" role="img"></i>
<span> {{ _('Costs') }} </span> <span> {{ _('Costs') }} </span>
</a> </a>
</li> </li>
<li> <li>
<a class="dropdown-item" id="btn-explain-buffers" href="#" tabindex="0"> <a class="dropdown-item" id="btn-explain-buffers" href="#" tabindex="0">
<i class="explain-buffers fa fa-check visibility-hidden" aria-hidden="true"></i> <i class="explain-buffers fa fa-check visibility-hidden" aria-hidden="true" role="img"></i>
<span> {{ _('Buffers') }} </span> <span> {{ _('Buffers') }} </span>
</a> </a>
</li> </li>
<li> <li>
<a class="dropdown-item" id="btn-explain-timing" href="#" tabindex="0"> <a class="dropdown-item" id="btn-explain-timing" href="#" tabindex="0">
<i class="explain-timing fa fa-check visibility-hidden" aria-hidden="true"></i> <i class="explain-timing fa fa-check visibility-hidden" aria-hidden="true" role="img"></i>
<span> {{ _('Timing') }} </span> <span> {{ _('Timing') }} </span>
</a> </a>
</li> </li>
<li data-min-ver="100000"> <li data-min-ver="100000">
<a class="dropdown-item" id="btn-explain-summary" href="#" tabindex="0"> <a class="dropdown-item" id="btn-explain-summary" href="#" tabindex="0">
<i class="explain-summary fa fa-check visibility-hidden" aria-hidden="true"></i> <i class="explain-summary fa fa-check visibility-hidden" aria-hidden="true" role="img"></i>
<span> {{ _('Summary') }} </span> <span> {{ _('Summary') }} </span>
</a> </a>
</li> </li>
<li data-min-ver="120000"> <li data-min-ver="120000">
<a class="dropdown-item" id="btn-explain-settings" href="#" tabindex="0"> <a class="dropdown-item" id="btn-explain-settings" href="#" tabindex="0">
<i class="explain-settings fa fa-check visibility-hidden" aria-hidden="true"></i> <i class="explain-settings fa fa-check visibility-hidden" aria-hidden="true" role="img"></i>
<span> {{ _('Settings') }} </span> <span> {{ _('Settings') }} </span>
</a> </a>
</li> </li>
@@ -324,12 +324,12 @@
title="" title=""
accesskey="" accesskey=""
tabindex="0" disabled> tabindex="0" disabled>
<i class="pg-font-icon icon-commit sql-icon-lg" aria-hidden="true"></i> <i class="pg-font-icon icon-commit sql-icon-lg" aria-hidden="true" role="img"></i>
</button> </button>
<button id="btn-rollback" type="button" class="btn btn-sm btn-secondary" <button id="btn-rollback" type="button" class="btn btn-sm btn-secondary"
title="" title=""
tabindex="0" disabled> tabindex="0" disabled>
<i class="pg-font-icon icon-rollback sql-icon-lg" aria-hidden="true"></i> <i class="pg-font-icon icon-rollback sql-icon-lg" aria-hidden="true" role="img"></i>
</button> </button>
</div> </div>
<div class="btn-group mr-1" role="group" aria-label=""> <div class="btn-group mr-1" role="group" aria-label="">
@@ -338,7 +338,7 @@
title="" title=""
accesskey="" accesskey=""
tabindex="0"> tabindex="0">
<i class="fa fa-eraser sql-icon-lg" aria-hidden="true"></i> <i class="fa fa-eraser sql-icon-lg" aria-hidden="true" role="img"></i>
</button> </button>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li> <li>
@@ -357,7 +357,7 @@
<button id="btn-download" type="button" class="btn btn-sm btn-secondary" <button id="btn-download" type="button" class="btn btn-sm btn-secondary"
title="" title=""
tabindex="0"> tabindex="0">
<i class="fa fa-download sql-icon-lg" aria-hidden="true"></i> <i class="fa fa-download sql-icon-lg" aria-hidden="true" role="img"></i>
</button> </button>
</div> </div>
</div> </div>
@@ -371,7 +371,7 @@
accesskey="" accesskey=""
tabindex="0"> tabindex="0">
<i class="pg-font-icon icon-query-tool-disconnected obtaining-conn d-flex m-auto" aria-hidden="true" <i class="pg-font-icon icon-query-tool-disconnected obtaining-conn d-flex m-auto" aria-hidden="true"
title=""> title="" role="img">
</i> </i>
</div> </div>
<div class="editor-title" <div class="editor-title"

View File

@@ -2118,7 +2118,7 @@ define('tools.querytool', [
alertify.confirm( alertify.confirm(
gettext('Connection Warning'), gettext('Connection Warning'),
'<p style="float:left">'+ '<p style="float:left">'+
'<span class="fa fa-exclamation-triangle warn-icon" aria-hidden="true">'+ '<span class="fa fa-exclamation-triangle warn-icon" aria-hidden="true" role="img">'+
'</span>'+ '</span>'+
'</p>'+ '</p>'+
'<p style="display: inline-block;">'+ '<p style="display: inline-block;">'+