From e9806e73f7d91f0810a298bc6c9139e6da138575 Mon Sep 17 00:00:00 2001 From: Rasmus Fuhse Date: Tue, 28 May 2024 12:58:57 +0000 Subject: Resolve "Barrierefreiheit: Globale Suche nicht barrierefrei nutzbar" Closes #4072 Merge request studip/studip!2918 --- lib/classes/globalsearch/GlobalSearchCourses.php | 4 +- .../globalsearch/GlobalSearchCourseware.php | 2 +- lib/classes/globalsearch/GlobalSearchMessages.php | 6 +-- lib/classes/globalsearch/GlobalSearchMyCourses.php | 4 +- lib/classes/globalsearch/GlobalSearchUsers.php | 2 +- .../assets/javascripts/bootstrap/global_search.js | 45 ++++++++++++++++++++++ resources/assets/javascripts/lib/global_search.js | 14 ++++--- .../assets/stylesheets/scss/globalsearch.scss | 4 +- templates/globalsearch/searchbar.php | 19 +++++++-- 9 files changed, 77 insertions(+), 23 deletions(-) diff --git a/lib/classes/globalsearch/GlobalSearchCourses.php b/lib/classes/globalsearch/GlobalSearchCourses.php index bf29ca0..9de5535 100644 --- a/lib/classes/globalsearch/GlobalSearchCourses.php +++ b/lib/classes/globalsearch/GlobalSearchCourses.php @@ -225,9 +225,9 @@ class GlobalSearchCourses extends GlobalSearchModule implements GlobalSearchFull array_map( function ($lecturer, $index) use ($search, $course) { if ($index < 3) { - return '' . self::mark($lecturer->getUserFullname(), $search) . ''; + return self::mark($lecturer->getUserFullname(), $search); } else if ($index == 3) { - return '... (' . _('mehr') . ') '; + return '... (' . _('mehr') . ')'; } }, $lecturers, diff --git a/lib/classes/globalsearch/GlobalSearchCourseware.php b/lib/classes/globalsearch/GlobalSearchCourseware.php index d4c53b1..de069fe 100644 --- a/lib/classes/globalsearch/GlobalSearchCourseware.php +++ b/lib/classes/globalsearch/GlobalSearchCourseware.php @@ -142,7 +142,7 @@ class GlobalSearchCourseware extends GlobalSearchModule implements GlobalSearchF 'description' => $description, 'url' => $pageData['url'], 'img' => $structural_element->image ? $structural_element->getImageUrl() : Icon::create('courseware')->asImagePath(), - 'additional' => '' . htmlReady($pageData['originName']) . '', + 'additional' => htmlReady($pageData['originName']), 'date' => $date->format('d.m.Y H:i'), 'structural-element-id' => $structural_element->id, 'expand' => null diff --git a/lib/classes/globalsearch/GlobalSearchMessages.php b/lib/classes/globalsearch/GlobalSearchMessages.php index d1a91a5..5f64b40 100644 --- a/lib/classes/globalsearch/GlobalSearchMessages.php +++ b/lib/classes/globalsearch/GlobalSearchMessages.php @@ -79,11 +79,7 @@ class GlobalSearchMessages extends GlobalSearchModule if ($user) { $username = $user->getFullName(); - $additional = sprintf( - '%s', - URLHelper::getLink('dispatch.php/profile', ['username' => $user->username]), - self::mark($user->getFullName(), $search) - ); + $additional = self::mark($user->getFullName(), $search); } } diff --git a/lib/classes/globalsearch/GlobalSearchMyCourses.php b/lib/classes/globalsearch/GlobalSearchMyCourses.php index f8f2f11..6558f78 100644 --- a/lib/classes/globalsearch/GlobalSearchMyCourses.php +++ b/lib/classes/globalsearch/GlobalSearchMyCourses.php @@ -162,9 +162,9 @@ class GlobalSearchMyCourses extends GlobalSearchModule array_map( function ($lecturer, $index) use ($search, $course) { if ($index < 3) { - return '' . self::mark($lecturer->getUserFullname(), $search) . ''; + return self::mark($lecturer->getUserFullname(), $search); } else if ($index == 3) { - return '... (' . _('mehr') . ') '; + return '... (' . _('mehr') . ')'; } }, $lecturers, diff --git a/lib/classes/globalsearch/GlobalSearchUsers.php b/lib/classes/globalsearch/GlobalSearchUsers.php index fb8677a..458f098 100644 --- a/lib/classes/globalsearch/GlobalSearchUsers.php +++ b/lib/classes/globalsearch/GlobalSearchUsers.php @@ -86,7 +86,7 @@ class GlobalSearchUsers extends GlobalSearchModule implements GlobalSearchFullte ['username' => $user->username], true ), - 'additional' => '' . self::mark($user->username, $search) . '', + 'additional' => self::mark($user->username, $search), 'expand' => self::getSearchURL($search), 'img' => Avatar::getAvatar($user->id)->getUrl(Avatar::MEDIUM), ]; diff --git a/resources/assets/javascripts/bootstrap/global_search.js b/resources/assets/javascripts/bootstrap/global_search.js index 4d0738e..a85f2f0 100644 --- a/resources/assets/javascripts/bootstrap/global_search.js +++ b/resources/assets/javascripts/bootstrap/global_search.js @@ -36,6 +36,51 @@ STUDIP.domReady(() => { return false; } }); + $('#globalsearch-input').on('keypress', function(e) { + if (e.which === 13) { + STUDIP.GlobalSearch.doSearch(); + return false; + } + }); + $('#globalsearch-searchbar').on('keydown', function(e) { + if (e.originalEvent.code === 'ArrowDown') { + if ($('#globalsearch-list [role=listitem]:focus').length === 0) { + $('#globalsearch-list [role=listitem]:visible').first().focus(); + } else { + let n = $('#globalsearch-list [role=listitem]:focus').next(); + if (n.length > 0 && n.is('[role=listitem]:visible')) { + n.focus(); + } else { + n = $('#globalsearch-list [role=listitem]:focus').parent().next().find('[role=listitem]:visible').first(); + if (n.length > 0) { + n.focus(); + } else { + $('#globalsearch-list [role=listitem]:visible').first().focus(); + } + } + } + return false; + } + if (e.originalEvent.code === 'ArrowUp') { + if ($('#globalsearch-list [role=listitem]:focus').length === 0) { + $('#globalsearch-list [role=listitem]:visible').last().focus(); + } else { + let n = $('#globalsearch-list [role=listitem]:focus').prev(); + if (n.length > 0 && n.is('[role=listitem]:visible')) { + n.focus(); + } else { + n = $('#globalsearch-list [role=listitem]:focus').parent().prev().find('[role=listitem]:visible').last(); + if (n.length > 0) { + n.focus(); + } else { + $('#globalsearch-list [role=listitem]:visible').last().focus(); + } + } + } + return false; + } + }); + // Close search on click on page. $('#navigation-level-1, #current-page-structure, #main-footer').on('click', function() { diff --git a/resources/assets/javascripts/lib/global_search.js b/resources/assets/javascripts/lib/global_search.js index 05a53aa..394b7e3 100644 --- a/resources/assets/javascripts/lib/global_search.js +++ b/resources/assets/javascripts/lib/global_search.js @@ -9,6 +9,7 @@ const GlobalSearch = { */ toggleSearchBar: function(visible, cleanup) { $('#globalsearch-searchbar').toggleClass('is-visible', visible); + $('#globalsearch-input').attr('aria-expanded', visible ? 'true' : 'false'); $('#globalsearch-input').toggleClass('hidden-small-down', !visible); $('#globalsearch-icon').toggleClass('hidden-small-down', visible); $('#globalsearch-clear').toggleClass('hidden-small-down', !visible); @@ -70,7 +71,7 @@ const GlobalSearch = { // Iterate over each result category. $.each(json, function(name, value) { // Create an
for category. - var category = $(`
`), + var category = $(`
`), header = $('
').appendTo(category), counter = 0; @@ -96,7 +97,7 @@ const GlobalSearch = { // Process results and create corresponding entries. $.each(value.content, function(index, result) { // Create single result entry. - var single = $('
'), + var single = $(``), data = $('
'), details = $('
'); @@ -107,17 +108,17 @@ const GlobalSearch = { // Which result types should be opened via dialog? const openInDialog = ['GlobalSearchFiles', 'GlobalSearchMessages']; var dataDialog = (openInDialog.indexOf(name) >= 0 ? dataDialog = 'data-dialog' : dataDialog = ''); - var link = $(``).appendTo(single); + //var link = $(``).appendTo(single); // Optional image... if (result.img !== null) { $(``) .wrap('
') .parent() // Element is now the wrapper - .appendTo(link); + .appendTo(single); } - link.append(data); + single.append(data); // Name/title $('