Koha/koha-tmpl/intranet-tmpl/prog/en/modules/common/patron_search.tt
Owen Leonard 6d6b2078c0 Bug 14193 - Accessibility: Searching patrons using the alphabetic index doesn't work
Using a mouse to click on the alphabetic index letters works even though
the anchor markup doesn't contain an href attribute. However you
can't tab to them using the keyboard, and I assume the issue with
screen readers is related.

This patch adds a dummy href attribute and a class-based click handler
so that we can get rid of the "onclick" attribute in the markup.

To test, apply the patch and visit the "Patrons" section.

1. Use the tab key to move the focus to one of the alphabet links.
2. Hit "Enter" and confirm that the search is performed correctly.
3. Click any of the alphabet links and confirm that clicking works as
   well.
4. View the details of any patron and click the "Add child" button.
5. In the "Guarantor information" section click the "Change" button.
6. In the search popup, use the tab key to move the focus to one of the
   alphabet links.
2. Hit "Enter" and confirm that the search is performed correctly.
3. Click any of the alphabet links and confirm that clicking works as
   well.

Signed-off-by: Briana <brianagreally@gmail.com>

Signed-off-by: Katrin Fischer <katrin.fischer.83@web.de>

Signed-off-by: Brendan Gallagher brendan@bywatersolutions.com
2016-01-23 18:50:47 +00:00

238 lines
8.6 KiB
Text

[% USE Koha %]
[% INCLUDE 'doc-head-open.inc' %]
<title>Koha &rsaquo; Patron search</title>
[% INCLUDE 'doc-head-close.inc' %]
<link rel="stylesheet" type="text/css" href="[% themelang %]/css/datatables.css" />
[% INCLUDE 'datatables.inc' %]
<script type="text/javascript">
//<![CDATA[
var search = 1;
$(document).ready(function(){
$("#info").hide();
$("#error").hide();
[% IF view != "show_results" %]
$("#searchresults").hide();
search = 0;
[% END %]
// Apply DataTables on the results table
dtMemberResults = $("#memberresultst").dataTable($.extend(true, {}, dataTablesDefaults, {
'bServerSide': true,
'sAjaxSource': "/cgi-bin/koha/svc/members/search",
'fnServerData': function(sSource, aoData, fnCallback) {
if ( ! search ) {
return;
}
aoData.push({
'name': 'searchmember',
'value': $("#searchmember_filter").val()
},{
'name': 'firstletter',
'value': $("#firstletter_filter").val()
},{
'name': 'categorycode',
'value': $("#categorycode_filter").val()
},{
'name': 'branchcode',
'value': $("#branchcode_filter").val()
},{
'name': 'name_sorton',
'value': 'borrowers.surname borrowers.firstname'
},{
'name': 'category_sorton',
'value': 'categories.description',
},{
'name': 'branch_sorton',
'value': 'branches.branchname'
},{
'name': 'template_path',
'value': '[% json_template %]',
},{
'name': 'selection_type',
'value': '[% selection_type %]',
}
[% IF patrons_with_acq_perm_only %]
,{
'name': 'has_permission',
'value': 'acquisition.order_manage',
}
[% END %]
);
$.ajax({
'dataType': 'json',
'type': 'POST',
'url': sSource,
'data': aoData,
'success': function(json){
fnCallback(json);
}
});
},
'aoColumns':[
[% FOR column IN columns %]
[% IF column == 'action' %]
{ 'mDataProp': 'dt_action', 'bSortable': false }
[% ELSIF column == 'address' %]
{ 'mDataProp': 'dt_address', 'bSortable': false }
[% ELSE %]
{ 'mDataProp': 'dt_[% column %]' }
[% END %]
[% UNLESS loop.last %],[% END %]
[% END %]
],
'bAutoWidth': false,
[% IF patrons_with_acq_perm_only %]
'bPaginate': false,
[% ELSE %]
'sPaginationType': 'full_numbers',
"iDisplayLength": [% Koha.Preference('PatronsPerPage') %],
[% END %]
'aaSorting': [[[% aaSorting || 0 %], 'asc']],
'bFilter': false,
'bProcessing': true,
}));
$("#searchform").on('submit', filter);
$(".filterByLetter").on("click",function(e){
e.preventDefault();
filterByFirstLetterSurname($(this).text());
});
});
function filter() {
search = 1;
$("#firstletter_filter").val('');
$("#searchresults").show();
dtMemberResults.fnDraw();
return false;
}
// User has clicked on a letter
function filterByFirstLetterSurname(letter) {
$("#firstletter_filter").val(letter);
search = 1;
$("#searchresults").show();
dtMemberResults.fnDraw();
}
// modify parent window owner element
[% IF selection_type == 'add' %]
function add_user(borrowernumber, borrowername) {
var p = window.opener;
// In one place (serials/routing.tt), the page is reload on every add
// We have to wait for the page to be there
function wait_for_opener () {
if ( ! $(opener.document).find('body').size() ) {
setTimeout(wait_for_opener, 500);
} else {
[%# Note that add_user could sent data instead of borrowername too %]
$("#info").hide();
$("#error").hide();
if ( p.add_user(borrowernumber, borrowername) < 0 ) {
$("#error").html(_("Borrower '%s' is already in the list.").format(borrowername));
$("#error").show();
} else {
$("#info").html(_("Borrower '%s' added.").format(borrowername));
$("#info").show();
}
}
}
wait_for_opener();
}
[% ELSIF selection_type == 'select' %]
function select_user(borrowernumber, data) {
var p = window.opener;
p.select_user(borrowernumber, data);
window.close();
}
[% END %]
//]]>
</script>
</head>
<body id="common_patron_search" class="common">
<div id="patron_search" class="yui-t7">
<div id="bd">
<div class="yui-g">
<form id="searchform">
<fieldset class="brief">
<h3>Search for patron</h3>
<ol>
<li>
<label for="searchmember_filter">Search:</label>
<input type="text" id="searchmember_filter" value="[% searchmember %]"/>
</li>
<li>
<label for="categorycode_filter">Category:</label>
<select id="categorycode_filter">
<option value="">Any</option>
[% FOREACH category IN categories %]
<option value="[% category.categorycode %]">[% category.description %]</option>
[% END %]
</select>
</li>
<li>
<label for="branchcode_filter">Library:</label>
<select id="branchcode_filter">
[% IF branches.size != 1 %]
<option value="">Any</option>
[% END %]
[% FOREACH branch IN branches %]
<option value="[% branch.branchcode %]">[% branch.branchname %]</option>
[% END %]
</select>
</li>
</ol>
<fieldset class="action">
<input class="btn btn-default" type="submit" value="Search" />
</fieldset>
</fieldset>
<form>
[% IF patrons_with_acq_perm_only %]
<div class="hint">Only staff with superlibrarian or acquisitions permissions (or order_manage permission if granular permissions are enabled) are returned in the search results</div>
[% END %]
<div class="browse">
Browse by last name:
[% FOREACH letter IN alphabet.split(' ') %]
<a href="#" class="filterByLetter">[% letter %]</a>
[% END %]
</div>
<div id="info" class="dialog message"></div>
<div id="error" class="dialog alert"></div>
<input type="hidden" id="firstletter_filter" value="" />
<div id="searchresults">
<table id="memberresultst">
<thead>
<tr>
[% FOR column IN columns %]
[% SWITCH column %]
[% CASE 'cardnumber' %]<th>Card</th>
[% CASE 'dateofbirth' %]<th>Date of birth</th>
[% CASE 'address' %]<th>Address</th>
[% CASE 'name' %]<th>Name</th>
[% CASE 'branch' %]<th>Library</th>
[% CASE 'category' %]<th>Category</th>
[% CASE 'dateexpiry' %]<th>Expires on</td>
[% CASE 'borrowernotes' %]<th>Notes</th>
[% CASE 'action' %]<th>&nbsp;</th>
[% END %]
[% END %]
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<div id="closewindow"><a href="#" class="btn btn-default close">Close</a></div>
</div>
</div>
[% INCLUDE 'intranet-bottom.inc' %]