diff --git a/local/languages/de.ini b/local/languages/de.ini index fc2852d71200a869d5c844346094cca46eb94636..6428ea9568274ecf180264ac9f35778dece09cc1 100644 --- a/local/languages/de.ini +++ b/local/languages/de.ini @@ -2054,7 +2054,6 @@ DE-Kn38 = "Hochschule für Musik und Tanz Köln" Range-from-to = "Bereich von/bis" ; #17833 -form-legend = "Bitte füllen Sie alle Felder aus" form-button-submit = "Ausgefülltes Formular abschicken" ; #17601 @@ -2079,4 +2078,6 @@ missing_record_exception = "Der aufgerufene Titel (%%id%%) ist nicht vorhanden." Unknown Electronic = "Titel ist beim Resolver-Service nicht bekannt" ; #20826 -title_wrapper = "%%pageTitle%% %%titleSeparator%% %%siteTitle%%" \ No newline at end of file +title_wrapper = "%%pageTitle%% %%titleSeparator%% %%siteTitle%%" + +load_tab_content_hint = "Klicken Sie hier, um den Inhalt der Registerkarte zu laden." diff --git a/local/languages/en.ini b/local/languages/en.ini index e3c2d98bdcae9c74408219a851055e1d2ed5d0cb..f1aa7b7cf478120dce8ec464464eec64899cca2b 100644 --- a/local/languages/en.ini +++ b/local/languages/en.ini @@ -1949,7 +1949,6 @@ resolver_link_access_unknown = "Record unknown to resolver" ; message to be shown upon empty resolver response no_resolver_links = "No online links available." - ; reset password reset_password_text = "Please complete the form below to reset your password. You will receive an email after we have completed resetting your password." Reset Password = "Reset Password" @@ -2136,7 +2135,6 @@ DE-Kn38 = "Hochschule für Musik und Tanz Köln" Range-from-to = "Range from/to" ; #17833 -form-legend = "Please fill in all fields to create an account" form-button-submit = "Submit the completed form" ; #17601 @@ -2167,4 +2165,6 @@ missing_record_exception = "Record %%id%% is unavailable." Unknown Electronic = "Record is unknown to the resolver service" ; #20826 -title_wrapper = "%%pageTitle%% %%titleSeparator%% %%siteTitle%%" \ No newline at end of file +title_wrapper = "%%pageTitle%% %%titleSeparator%% %%siteTitle%%" + +load_tab_content_hint = "Click to load tab content." diff --git a/themes/finc-accessibility/js/record.js b/themes/finc-accessibility/js/record.js new file mode 100644 index 0000000000000000000000000000000000000000..9766867212c7524e3ed39a0a6eac7c250fc27d76 --- /dev/null +++ b/themes/finc-accessibility/js/record.js @@ -0,0 +1,323 @@ +/*global deparam, getUrlRoot, grecaptcha, recaptchaOnLoad, resetCaptcha, syn_get_widget, userIsLoggedIn, VuFind, setupJumpMenus */ +/*exported ajaxTagUpdate, recordDocReady, refreshTagListCallback */ + +/** + * Functions and event handlers specific to record pages. + */ +function checkRequestIsValid(element, requestType) { + var recordId = element.href.match(/\/Record\/([^/]+)\//)[1]; + var vars = deparam(element.href); + vars.id = recordId; + + var url = VuFind.path + '/AJAX/JSON?' + $.param({ + method: 'checkRequestIsValid', + id: recordId, + requestType: requestType, + data: vars + }); + $.ajax({ + dataType: 'json', + cache: false, + url: url + }) + .done(function checkValidDone(response) { + if (response.data.status) { + $(element).removeClass('disabled') + .attr('title', response.data.msg) + .html('<i class="fa fa-flag" aria-hidden="true"></i> ' + response.data.msg); + } else { + $(element).remove(); + } + }) + .fail(function checkValidFail(/*response*/) { + $(element).remove(); + }); +} + +function setUpCheckRequest() { + $('.checkRequest').each(function checkRequest() { + checkRequestIsValid(this, 'Hold'); + }); + $('.checkStorageRetrievalRequest').each(function checkStorageRetrievalRequest() { + checkRequestIsValid(this, 'StorageRetrievalRequest'); + }); + $('.checkILLRequest').each(function checkILLRequest() { + checkRequestIsValid(this, 'ILLRequest'); + }); +} + +function deleteRecordComment(element, recordId, recordSource, commentId) { + var url = VuFind.path + '/AJAX/JSON?' + $.param({ method: 'deleteRecordComment', id: commentId }); + $.ajax({ + dataType: 'json', + url: url + }) + .done(function deleteCommentDone(/*response*/) { + $($(element).closest('.comment')[0]).remove(); + }); +} + +function refreshCommentList($target, recordId, recordSource) { + var url = VuFind.path + '/AJAX/JSON?' + $.param({ + method: 'getRecordCommentsAsHTML', + id: recordId, + source: recordSource + }); + $.ajax({ + dataType: 'json', + url: url + }) + .done(function refreshCommentListDone(response) { + // Update HTML + var $commentList = $target.find('.comment-list'); + $commentList.empty(); + $commentList.append(response.data.html); + $commentList.find('.delete').unbind('click').click(function commentRefreshDeleteClick() { + var commentId = $(this).attr('id').substr('recordComment'.length); + deleteRecordComment(this, recordId, recordSource, commentId); + return false; + }); + $target.find('.comment-form input[type="submit"]').button('reset'); + resetCaptcha($target); + }); +} + +function registerAjaxCommentRecord(_context) { + var context = typeof _context === "undefined" ? document : _context; + // Form submission + $(context).find('form.comment-form').unbind('submit').submit(function commentFormSubmit() { + var form = this; + var id = form.id.value; + var recordSource = form.source.value; + var url = VuFind.path + '/AJAX/JSON?' + $.param({ method: 'commentRecord' }); + var data = { + comment: form.comment.value, + id: id, + source: recordSource + }; + if (typeof grecaptcha !== 'undefined') { + var recaptcha = $(form).find('.g-recaptcha'); + if (recaptcha.length > 0) { + data['g-recaptcha-response'] = grecaptcha.getResponse(recaptcha.data('captchaId')); + } + } + $.ajax({ + type: 'POST', + url: url, + data: data, + dataType: 'json' + }) + .done(function addCommentDone(/*response, textStatus*/) { + var $form = $(form); + var $tab = $form.closest('.list-tab-content'); + if (!$tab.length) { + $tab = $form.closest('.tab-pane'); + } + refreshCommentList($tab, id, recordSource); + $form.find('textarea[name="comment"]').val(''); + $form.find('input[type="submit"]').button('loading'); + resetCaptcha($form); + }) + .fail(function addCommentFail(response, textStatus) { + if (textStatus === 'abort' || typeof response.responseJSON === 'undefined') { return; } + VuFind.lightbox.alert(response.responseJSON.data, 'danger'); + }); + return false; + }); + // Delete links + $('.delete').click(function commentDeleteClick() { + var commentId = this.id.substr('recordComment'.length); + deleteRecordComment(this, $('.hiddenId').val(), $('.hiddenSource').val(), commentId); + return false; + }); + // Prevent form submit + return false; +} + +function registerTabEvents() { + // Logged in AJAX + registerAjaxCommentRecord(); + // Render recaptcha + recaptchaOnLoad(); + + setUpCheckRequest(); + + VuFind.lightbox.bind('.tab-pane.active'); +} + +function removeHashFromLocation() { + if (window.history.replaceState) { + var href = window.location.href.split('#'); + window.history.replaceState({}, document.title, href[0]); + } else { + window.location.hash = '#'; + } +} + +function ajaxLoadTab($newTab, tabid, setHash) { + // Request the tab via AJAX: + $.ajax({ + url: VuFind.path + getUrlRoot(document.URL) + '/AjaxTab', + type: 'POST', + data: {tab: tabid} + }) + .always(function ajaxLoadTabDone(data) { + if (typeof data === 'object') { + $newTab.html(data.responseText ? data.responseText : VuFind.translate('error_occurred')); + } else { + $newTab.html(data); + } + registerTabEvents(); + if (typeof syn_get_widget === "function") { + syn_get_widget(); + } + if (typeof setHash == 'undefined' || setHash) { + window.location.hash = tabid; + } else { + removeHashFromLocation(); + } + setupJumpMenus($newTab); + }); + return false; +} + +function refreshTagList(_target, _loggedin) { + var loggedin = !!_loggedin || userIsLoggedIn; + var target = _target || document; + var recordId = $(target).find('.hiddenId').val(); + var recordSource = $(target).find('.hiddenSource').val(); + var $tagList = $(target).find('.tagList'); + if ($tagList.length > 0) { + var url = VuFind.path + '/AJAX/JSON?' + $.param({ + method: 'getRecordTags', + id: recordId, + source: recordSource + }); + $.ajax({ + dataType: 'json', + url: url + }) + .done(function getRecordTagsDone(response) { + $tagList.empty(); + $tagList.replaceWith(response.data.html); + if (loggedin) { + $tagList.addClass('loggedin'); + } else { + $tagList.removeClass('loggedin'); + } + }); + } +} +function refreshTagListCallback() { + refreshTagList(false, true); +} + +function ajaxTagUpdate(_link, tag, _remove) { + var link = _link || document; + var remove = _remove || false; + var $target = $(link).closest('.record'); + var recordId = $target.find('.hiddenId').val(); + var recordSource = $target.find('.hiddenSource').val(); + $.ajax({ + url: VuFind.path + '/AJAX/JSON?method=tagRecord', + method: 'POST', + data: { + tag: '"' + tag.replace(/\+/g, ' ') + '"', + id: recordId, + source: recordSource, + remove: remove + } + }) + .always(function tagRecordAlways() { + refreshTagList($target, false); + }); +} + +function getNewRecordTab(tabid) { + return $('<div class="tab-pane ' + tabid + '-tab" id="' + tabid + '" role="tabpanel" tabindex="-1" aria-labelledby="' + tabid + '-tabselector"><i class="fa fa-spinner fa-spin" aria-hidden="true"></i> ' + VuFind.translate('loading') + '...</div>'); +} + +function backgroundLoadTab(tabid) { + if ($('.' + tabid + '-tab').length > 0) { + return; + } + var newTab = getNewRecordTab(tabid); + $('.nav-tabs a.' + tabid).closest('.result,.record').find('.tab-content').append(newTab); + return ajaxLoadTab(newTab, tabid, false); +} + +function applyRecordTabHash() { + var activeTab = $('.record-tabs li.active').attr('data-tab'); + var $initiallyActiveTab = $('.record-tabs li.initiallyActive a'); + var newTab = typeof window.location.hash !== 'undefined' + ? window.location.hash.toLowerCase() : ''; + + // Open tab in url hash + if (newTab.length <= 1 || newTab === '#tabnav') { + $initiallyActiveTab.click(); + } else if (newTab.length > 1 && '#' + activeTab !== newTab) { + $('.' + newTab.substr(1) + ' a').click(); + } +} + +$(window).on('hashchange', applyRecordTabHash); + +function recordDocReady() { + $('.record-tabs .nav-tabs a').click(function recordTabsClick() { + var $li = $(this).parent(); + // If it's an active tab, click again to follow to a shareable link. + if ($li.hasClass('active')) { + return true; + } + var tabid = $li.attr('data-tab'); + var $top = $(this).closest('.record-tabs'); + + // accessibility: mark tab controls as selected + $top.find('.record-tab.active').find('a').attr('aria-selected', 'false'); + $('#' + tabid + '-tabselector').attr('aria-selected', 'true').attr('aria-controls', tabid); + + // accessibility: set aria-hidden for content panes + $top.find('.tab-pane.active').removeClass('active').attr('aria-hidden', 'true'); + $top.find('.' + tabid + '-tab').addClass('active').attr('aria-hidden', 'false'); + + // if we're flagged to skip AJAX for this tab, we need special behavior: + if ($li.hasClass('noajax')) { + // if this was the initially active tab, we have moved away from it and + // now need to return -- just switch it back on. + if ($li.hasClass('initiallyActive')) { + $(this).tab('show'); + window.location.hash = 'tabnav'; + return false; + } + // otherwise, we need to let the browser follow the link: + return true; + } + $(this).tab('show'); + if ($top.find('.' + tabid + '-tab').length > 0) { + $top.find('.' + tabid + '-tab').addClass('active'); + if ($top.find('#' + tabid ).length) { + $top.find('#' + tabid ).parent().focus(); + } + if ($(this).parent().hasClass('initiallyActive')) { + removeHashFromLocation(); + } else { + window.location.hash = tabid; + } + return false; + } else { + var newTab = getNewRecordTab(tabid).addClass('active'); + $top.find('.tab-content').append(newTab); + if ($top.find('#' + tabid ).length) { + $top.find('#' + tabid ).parent().focus(); + } + return ajaxLoadTab(newTab, tabid, !$(this).parent().hasClass('initiallyActive')); + } + }); + + $('[data-background]').each(function setupBackgroundTabs(index, el) { + backgroundLoadTab(el.className); + }); + + registerTabEvents(); + applyRecordTabHash(); +} diff --git a/themes/finc-accessibility/js/vendor/bootstrap-accessibility-en.min.js b/themes/finc-accessibility/js/vendor/bootstrap-accessibility-en.min.js index 630f112aed7e6a0149687a95215c623908bf0404..fb3ad97f9a4462ee6e30273db5a316df5ee84feb 100644 --- a/themes/finc-accessibility/js/vendor/bootstrap-accessibility-en.min.js +++ b/themes/finc-accessibility/js/vendor/bootstrap-accessibility-en.min.js @@ -3,7 +3,6 @@ * Copyright (c) 2020 PayPal Accessibility Team; Licensed BSD */ !function ($) { "use strict"; - console.log('en'); var uniqueId = function (prefix) { return (prefix || "ui-id") + "-" + Math.floor(1e3 * Math.random() + 1) }, focusable = function (element, isTabIndexNotNaN) { diff --git a/themes/finc-accessibility/scss/compiled.scss b/themes/finc-accessibility/scss/compiled.scss index 766002b57789f053a07aea5a5099e79b2f515732..db481aca78be66dffc9e30ba18c9a77e01996dbd 100644 --- a/themes/finc-accessibility/scss/compiled.scss +++ b/themes/finc-accessibility/scss/compiled.scss @@ -54,4 +54,10 @@ a.remove-filter { display: flex; width: 100%; +} + +.record-tab.active{ + .load-tab-content { + display: none; + } } \ No newline at end of file diff --git a/themes/finc-accessibility/templates/Recommend/SideFacets/cluster-list.phtml b/themes/finc-accessibility/templates/Recommend/SideFacets/cluster-list.phtml index 293af05732827251527ee22b281cc69fe25b3cae..1b1f8adcbba51d11ecdae3e1785993b1e8cfff98 100644 --- a/themes/finc-accessibility/templates/Recommend/SideFacets/cluster-list.phtml +++ b/themes/finc-accessibility/templates/Recommend/SideFacets/cluster-list.phtml @@ -30,7 +30,7 @@ ]) ?> <?php endforeach; ?> <?php if (empty($this->cluster['list'])): ?> - <div class="facet"><?=$this->transEsc('facet_list_empty')?></div> + <span class="facet"><?=$this->transEsc('facet_list_empty')?></span> <?php endif; ?> <?php /* LESS and SEE MORE links */ ?> diff --git a/themes/finc-accessibility/templates/Recommend/SideFacets/filter-list.phtml b/themes/finc-accessibility/templates/Recommend/SideFacets/filter-list.phtml index 3957f6ba12e6ac722e65ea77266a15df592e7e73..3d2c763fce3e185c1e9f000fd9d06f4856a12c75 100644 --- a/themes/finc-accessibility/templates/Recommend/SideFacets/filter-list.phtml +++ b/themes/finc-accessibility/templates/Recommend/SideFacets/filter-list.phtml @@ -1,7 +1,7 @@ <!-- finc-accessibility - Recommend - SideFacets - filter-list.phtml --> <?php /* #18509 copied from bootstrap for adding language tags to displayText */ ?> <div class="facet-group active-filters"> - <div class="title"><?=$this->transEsc('Remove Filters')?> <span class="sr-only"><?=$this->transEsc('facet_deselect_hint') ?></div> + <div class="title"><?=$this->transEsc('Remove Filters')?> <span class="sr-only"><?=$this->transEsc('facet_deselect_hint') ?></span></div> <ul> <?php foreach ($filterList as $field => $filters): ?> <?php foreach ($filters as $i => $filter): ?> diff --git a/themes/finc/js/lightbox.js b/themes/finc/js/lightbox.js index 4d183e226b88d770ccea6bb32f1779abf431f7cd..ae7297e5b0f6290395b5d785dbaba82add5a3a94 100644 --- a/themes/finc/js/lightbox.js +++ b/themes/finc/js/lightbox.js @@ -114,6 +114,16 @@ VuFind.register('lightbox', function Lightbox() { $('#modal').find('.checkbox-select-item').change(function lbSelectAllDisable() { $(this).closest('.modal-body').find('.checkbox-select-all').prop('checked', false); }); + + // #19695 accessibility: set id for aria-label + if (_modalBody.find('h1').length) { + _modalBody.find('h1:first').attr('id', 'modal-title'); + $('#modal').attr('aria-labelledby', 'modal-title'); + } else if (_modalBody.find('h2').length) { + _modalBody.find('h2:first').attr('id', 'modal-title'); + $('#modal').attr('aria-labelledby', 'modal-title'); + } + // Recaptcha recaptchaOnLoad(); } diff --git a/themes/finc/templates/Recommend/SideFacets.phtml b/themes/finc/templates/Recommend/SideFacets.phtml index 8c7fff5acfa902339f2eaf28c3f5376178d00a96..3e524b476825eedf817ba8fa2c8b110c3aadf186 100644 --- a/themes/finc/templates/Recommend/SideFacets.phtml +++ b/themes/finc/templates/Recommend/SideFacets.phtml @@ -55,9 +55,9 @@ if ($hierarchicalFacets) { <?php if (!empty($sideFacetSet) && $results->getResultTotal() > 0): ?> <?php foreach ($sideFacetSet as $title => $cluster): ?> <div class="facet-group" id="side-panel-<?=$this->escapeHtmlAttr($title)?>"> - <button <?php if(in_array($title, $collapsedFacets)): ?>class="title collapsed" aria-expanded="false"<?php else: ?>class="title" aria-expanded="true"<?php endif ?> data-toggle="collapse" href="#side-collapse-<?=$this->escapeHtmlAttr($title) ?>" > + <a <?php if(in_array($title, $collapsedFacets)): ?>class="title collapsed" aria-expanded="false"<?php else: ?>class="title" aria-expanded="true"<?php endif ?> data-toggle="collapse" href="#side-collapse-<?=$this->escapeHtmlAttr($title) ?>" > <?=$this->transEsc($cluster['label'])?> <span class="sr-only"><?=$this->transEsc('facet_select_hint') ?></span> - </button> + </a> <ul id="side-collapse-<?=$this->escapeHtmlAttr($title)?>" class="collapse<?php if (!in_array($title, $collapsedFacets)): ?> in<?php endif ?>"> <?=$this->context($this)->renderInContext( 'Recommend/SideFacets/facet.phtml', diff --git a/themes/finc/templates/RecordDriver/DefaultRecord/link-isn.phtml b/themes/finc/templates/RecordDriver/DefaultRecord/link-isn.phtml index 77bed61f58f3b6a7a2cfc3113ec6a2fbb194be64..30507b95f9bba7a18fa8cdd5d980856dfd166994 100644 --- a/themes/finc/templates/RecordDriver/DefaultRecord/link-isn.phtml +++ b/themes/finc/templates/RecordDriver/DefaultRecord/link-isn.phtml @@ -1,9 +1,9 @@ <?php /* use advanced search if we have multiple issns */ if (is_array($this->lookfor) && count($this->lookfor) > 1) { - $query = '?join=AND&bool0[]=OR'; + $query = '?join=AND&bool0%5B%5D=OR'; foreach ($this->lookfor as $issn) { - $query .= '&lookfor0[]=' . urlencode($issn) . '&type0[]=ISN'; + $query .= '&lookfor0%5B%5D=' . urlencode($issn) . '&type0%5B%5D=ISN'; } } elseif (count($this->lookfor) == 1) { $query = '?lookfor=%22' . urlencode($this->lookfor[0]) . '%22&type=ISN'; diff --git a/themes/finc/templates/RecordDriver/SolrAI/result-list.phtml b/themes/finc/templates/RecordDriver/SolrAI/result-list.phtml index e21b80019c88987fa4b300e1455720c988b77584..63c4ed5c15e04155f7917b395ef565e2dd4f658b 100644 --- a/themes/finc/templates/RecordDriver/SolrAI/result-list.phtml +++ b/themes/finc/templates/RecordDriver/SolrAI/result-list.phtml @@ -4,6 +4,7 @@ $coverDetails = $this->record($this->driver)->getCoverDetails('result-list', 'me $cover = $coverDetails['html']; $thumbnail = false; $thumbnailAlignment = $this->record($this->driver)->getThumbnailAlignment('result'); +$describedById = $driver->getSourceIdentifier() . '|' . $driver->getUniqueId(); if ($cover): ob_start(); ?> <div class="media-<?=$thumbnailAlignment?> <?=$this->escapeHtmlAttr($coverDetails['size'])?>" aria-hidden="true"> @@ -31,7 +32,7 @@ if ($cover): <div class="media-body"> <div class="result-body"> <div> - <a href="<?=$this->recordLink()->getUrl($this->driver)?>" class="title getFull" data-view="<?=$this->params->getOptions()->getListViewOption()?>" lang=""> + <a id="<?=$describedById?>" href="<?=$this->recordLink()->getUrl($this->driver)?>" class="title getFull" data-view="<?=$this->params->getOptions()->getListViewOption()?>" lang=""> <?=$this->record($this->driver)->getTitleHtml()?> </a> </div> diff --git a/themes/finc/templates/header.phtml b/themes/finc/templates/header.phtml index 50d239b701eb65722cd1115f6bdc0c405fae1650..67b8f3acd01568715ac098fdb5c6741fe52f82d9 100644 --- a/themes/finc/templates/header.phtml +++ b/themes/finc/templates/header.phtml @@ -109,7 +109,7 @@ <?php foreach ($this->layout()->allLangs as $langCode => $langName): ?> <?php if ($langCode !== $this->layout()->userLang) : ?> <li> - <button type="submit" class="btn <?=(count($this->layout()->allLangs) == 2) ? ' btn-secondary' : ''?>" href="#" onClick="document.langForm.mylang.value='<?=$langCode?>';document.langForm.submit()"> + <button type="submit" class="btn <?=(count($this->layout()->allLangs) == 2) ? ' btn-secondary' : ''?>" data-href="#" onClick="document.langForm.mylang.value='<?=$langCode?>';document.langForm.submit()"> <span class="visible-sm-md-only"><?=$langCode?></span> <span class="hidden-sm-md"><?=$this->displayLanguageOption($langName)?></span> </button> @@ -127,8 +127,8 @@ <?php /* finc searchbox: we use searchbox here so it becomes part of the sticky header, we need to place this after the navbar-right for anything but mobile - see flex-container in SCSS:*/ ?> <?php if ($this->layout()->searchbox !== false): ?> - <div class="search container"> - <nav class="nav searchbox hidden-print" role="search"> + <div class="search container" role="search"> + <nav class="nav searchbox hidden-print"> <?=$this->layout()->searchbox?> </nav> </div> diff --git a/themes/finc/templates/layout/layout.phtml b/themes/finc/templates/layout/layout.phtml index a269a91e3a942567214f3c2f97c6b620544988bb..8f4a34ab4c74a4cf5262f19e35e5843b65ff16ab 100644 --- a/themes/finc/templates/layout/layout.phtml +++ b/themes/finc/templates/layout/layout.phtml @@ -257,7 +257,7 @@ if (!isset($this->layout()->searchbox)) { <!-- MODAL IN CASE WE NEED ONE --> <?php /* move X button to logical pos. in structure + make accessible via tab - CK */ ?> -<div id="modal" class="modal fade hidden-print" tabindex="-1" role="dialog" aria-modal="true" aria-labelledby="modal-title" aria-hidden="true" aria-describedby="modal-description"> +<div id="modal" class="modal fade hidden-print" tabindex="-1" role="dialog" aria-modal="true" aria-hidden="true" aria-describedby="modal-description"> <div class="modal-dialog"> <div class="modal-content"> <button type="button" class="close" data-dismiss="modal" tabindex="0" aria-label="<?= $this->transEsc('CloseModal') ?>"> diff --git a/themes/finc/templates/myresearch/account.phtml b/themes/finc/templates/myresearch/account.phtml index b1055a8c55baea6e4f76428bbad1ef93d11cedae..f4e40c2f045ce098ba788dd2cc29355671bfa88a 100644 --- a/themes/finc/templates/myresearch/account.phtml +++ b/themes/finc/templates/myresearch/account.phtml @@ -11,7 +11,6 @@ <?=$this->flashmessages()?> <form method="post" name="accountForm" id="accountForm" class="form-user-create" data-toggle="validator" role="form"> - <legend class="sr-only"><?=$this->transEsc('form-legend')?></legend> <?=$this->auth()->getCreateFields()?> <?=$this->recaptcha()->html($this->useRecaptcha) ?> <div class="form-group"> diff --git a/themes/finc/templates/myresearch/newpassword.phtml b/themes/finc/templates/myresearch/newpassword.phtml index b2102e7315a77aac2af970fed31039ebc427488a..e493278a4bcba753d7aed4bbb79edfc44bffe16a 100644 --- a/themes/finc/templates/myresearch/newpassword.phtml +++ b/themes/finc/templates/myresearch/newpassword.phtml @@ -23,7 +23,6 @@ <div class="error"><?=$this->transEsc('recovery_user_not_found') ?></div> <?php else: ?> <form id="newpassword" class="form-new-password" action="<?=$this->url('myresearch-newpassword') ?>" method="post" data-toggle="validator" role="form"> - <legend class="sr-only"><?=$this->transEsc('form-legend')?></legend> <input type="hidden" value="<?=$this->escapeHtmlAttr($this->auth()->getManager()->getCsrfHash())?>" name="csrf"/> <input type="hidden" value="<?=$this->escapeHtmlAttr($this->hash) ?>" name="hash"/> <input type="hidden" value="<?=$this->escapeHtmlAttr($this->username) ?>" name="username"/> diff --git a/themes/finc/templates/record/cart-buttons.phtml b/themes/finc/templates/record/cart-buttons.phtml index edb7d83ea32988fbf3970619cf617a6174abcc5b..beaa7cbe11028a7347ce015293c8cd923e53f0b9 100644 --- a/themes/finc/templates/record/cart-buttons.phtml +++ b/themes/finc/templates/record/cart-buttons.phtml @@ -3,7 +3,7 @@ <?php if ($cart->isActive()): ?> <?php $cartId = $this->source . '|' . $this->id; ?> - <span class="btn-bookbag-toggle" data-cart-id="<?=$this->escapeHtmlAttr($this->id)?>" data-cart-source="<?=$this->escapeHtmlAttr($this->source)?>"> + <div class="btn-bookbag-toggle" data-cart-id="<?=$this->escapeHtmlAttr($this->id)?>" data-cart-source="<?=$this->escapeHtmlAttr($this->source)?>"> <?php /* Make add-to/remove-from bookbag accessible for keyboard navigation - CK */ ?> <a class="cart-add hidden<?php if (!$cart->contains($cartId)): ?> correct<?php endif ?>" href="javascript:" tabindex="0"> <i class="cart-link-icon fa fa-plus" aria-hidden="true"></i><span class="cart-link-label"><?=$this->transEsc('Add to Book Bag')?></span> @@ -11,16 +11,17 @@ <a class="cart-remove hidden<?php if ($cart->contains($cartId)): ?> correct<?php endif ?>" href="javascript:" tabindex="0"> <i class="cart-link-icon fa fa-minus-circle" aria-hidden="true"></i> <span class="cart-link-label"><?=$this->transEsc('Remove from Book Bag')?></span> </a> - <noscript> - <form method="post" name="addForm" action="<?=$this->url('cart-processor')?>"> + <form class="cartProcessorNoJs" method="post" name="addForm" action="<?=$this->url('cart-processor')?>"> + <noscript> <input type="hidden" name="ids[]" value="<?=$this->escapeHtmlAttr($cartId)?>"/> <?php if ($cart->contains($cartId)): ?> <input class="btn btn-default" type="submit" name="delete" value="<?=$this->transEsc('Remove from Book Bag')?>"/> <?php else: ?> <input class="btn btn-default" type="submit" name="add" value="<?=$this->transEsc('Add to Book Bag')?>"/> <?php endif; ?> - </form> - </noscript> - </span> + </noscript> + </form> + <script>$(document).ready(function() { $(".cartProcessorNoJs").css('display', 'none'); });</script> + </div> <?php endif; ?> <!-- finc: record - cart-buttons END --> diff --git a/themes/finc/templates/record/view.phtml b/themes/finc/templates/record/view.phtml index 1f97d387fad4ff410d80c391850a4220a5bfe5a1..3749c2121c6fc81e1f807f1b38c5e40014cb3a48 100644 --- a/themes/finc/templates/record/view.phtml +++ b/themes/finc/templates/record/view.phtml @@ -40,15 +40,17 @@ <?= $this->record($this->driver)->getCoreMetadata() ?> <?php if (count($this->tabs) > 0): ?> - <a name="tabnav"></a> + <?php /* swap deprecated 'name' for 'ID' - CK */ ?> + <a id="tabnav"></a> <div class="record-tabs"> + <?php /* DO NOT add 'role=tablist' for accessibility, see #19938 - CK */ ?> <ul class="nav nav-tabs"> <?php foreach ($this->tabs as $tab => $obj): ?> <?php // add current tab to breadcrumbs if applicable: $desc = $obj->getDescription(); $tabName = preg_replace("/\W/", "-", strtolower($tab)); $tabClasses = ['record-tab', $tabName]; - if (0 === strcasecmp($this->activeTab, $tab)) { + if (($isActiveTab = 0 === strcasecmp($this->activeTab, $tab))) { if (!$this->loadInitialTabWithAjax || !$obj->supportsAjax()) { $tabClasses[] = 'active'; } @@ -63,16 +65,27 @@ $tabClasses[] = 'noajax'; } ?> + <?php /* DO NOT add role="tab" BUT DO ADD aria-controls and ID for accessibility -- + 'aria-selected' (true/false) needs to be set via record.js - CK */ ?> <li class="<?= implode(' ', $tabClasses) ?>" data-tab="<?= $tabName ?>"> - <a - href="<?= $this->recordLink()->getTabUrl($this->driver, $tab) ?>#tabnav"<?php if ($obj->supportsAjax() && in_array($tab, $this->backgroundTabs)): ?> data-background<?php endif ?>><?= $this->transEsc($desc) ?></a> + <a href="<?= $this->recordLink()->getTabUrl($this->driver, $tab) ?>#tabnav" + <?php if ($obj->supportsAjax() && in_array($tab, $this->backgroundTabs)): ?> data-background<?php endif ?> + aria-selected="<?= $isActiveTab ? "true" : "false" ?>" + aria-controls="<?= $tabName ?>" + id="<?= $tabName ?>-tabselector"> + <?= $this->transEsc($desc) ?> + <span class="sr-only load-tab-content"><?= $this->transEsc('load_tab_content_hint') ?></span></a> </li> <?php endforeach; ?> </ul> - <div class="tab-content"> + <div class="tab-content" aria-live="polite" tabindex="-1"> <?php if (!$this->loadInitialTabWithAjax || !isset($activeTabObj) || !$activeTabObj->supportsAjax()): ?> - <div class="tab-pane active <?= $this->escapeHtmlAttr($this->activeTab) ?>-tab"> + <?php /* Add ID, role and aria-labelledby for accessibility - CK */ ?> + <div class="tab-pane active <?= $this->escapeHtmlAttr($this->activeTab) ?>-tab" + role="tabpanel" + id="<?= $this->escapeHtmlAttr($this->activeTab) ?>" + aria-labelledby="<?= $this->activeTab ?>-tabselector"> <?= isset($activeTabObj) ? $this->record($this->driver)->getTab($activeTabObj) : '' ?> </div> <?php endif; ?> diff --git a/themes/finc/templates/search/results.phtml b/themes/finc/templates/search/results.phtml index de9ade6fd08919a365af15829592376107b95f24..8bac2e91e997dee739e6556a1349061de5c306b5 100644 --- a/themes/finc/templates/search/results.phtml +++ b/themes/finc/templates/search/results.phtml @@ -85,15 +85,15 @@ $this->headScript()->appendFile("check_save_statuses.js"); <?php if ($recordTotal > 0): ?> <?php /* finc: use spans for easier to show/hide choices - CK */ ?> <div class="search-controls"> - <span class="limit"> + <div class="limit"> <?=$this->render('search/controls/limit.phtml')?> - </span> - <span class="sort right"> + </div> + <div class="sort right"> <?=$this->render('search/controls/sort.phtml')?> - </span> - <span class="view"> + </div> + <div class="view"> <?=$this->render('search/controls/view.phtml')?> - </span> + </div> </div> <?php endif; ?> </div>