Bug 22807: Add 'Skip to content' option

This patch adds a 'Skip to content' link to the header bar which will
only appear upon the first use of 'tab' to navigate after any fresh page
load in the OPAC.

Test plan
1/ Load any page in the OPAC
2/ Hit the `tab` key
3/ Note the new 'Skip to main content' link appears at the top left of
the screen.
4/ Hit `Enter` or Click the button
5/ Note the page scrolls to the area of the page that has the first block
   containing a .maincontent class.
6/ Note that the next available focusable element after the first .maincontent
   block has been given focus.
7/ Note that the link has been hidden

Signed-off-by: Hayley Mapley <hayleymapley@catalyst.net.nz>

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

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
(cherry picked from commit c36560a1ad)

Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
This commit is contained in:
Martin Renvoize 2020-06-09 14:10:53 +01:00 committed by Lucas Gass
parent 987eb51a33
commit c8da2d3278
2 changed files with 47 additions and 0 deletions

View File

@ -12,6 +12,7 @@
<div class="navbar navbar-inverse navbar-static-top">
<div class="navbar-inner">
<div class="container-fluid">
<button id="scrolltocontent" class="sr-only sr-only-focusable pull-left nav btn btn-danger" type="button">Skip to main content</button>
<h1 id="logo">
<a class="brand" href="/cgi-bin/koha/opac-main.pl">
[% IF ( LibraryNameTitle ) %]

View File

@ -113,3 +113,49 @@ function confirmModal(message, title, yes_label, no_label, callback) {
$("#bootstrap-confirm-box-modal-cancel").text( no_label || 'Cancel' );
$("#bootstrap-confirm-box-modal").modal('show');
}
//Add jQuery :focusable selector
(function($) {
function visible(element) {
return $.expr.filters.visible(element) && !$(element).parents().addBack().filter(function() {
return $.css(this, 'visibility') === 'hidden';
}).length;
}
function focusable(element, isTabIndexNotNaN) {
var map, mapName, img, nodeName = element.nodeName.toLowerCase();
if ('area' === nodeName) {
map = element.parentNode;
mapName = map.name;
if (!element.href || !mapName || map.nodeName.toLowerCase() !== 'map') {
return false;
}
img = $('img[usemap=#' + mapName + ']')[0];
return !!img && visible(img);
}
return (/input|select|textarea|button|object/.test(nodeName) ?
!element.disabled :
'a' === nodeName ?
element.href || isTabIndexNotNaN :
isTabIndexNotNaN) &&
// the element and all of its ancestors must be visible
visible(element);
}
$.extend($.expr[':'], {
focusable: function(element) {
return focusable(element, !isNaN($.attr(element, 'tabindex')));
}
});
})(jQuery);
$("#scrolltocontent").click(function() {
var content = $(".maincontent");
if (content.length > 0) {
$('html,body').animate({
scrollTop: content.first().offset().top
},
'slow');
content.first().find(':focusable').eq(0).focus();
}
});