Skip to content

Commit 07a6180

Browse files
Merge pull request #271 from MITLibraries/use-180
Define new helper for tab links, with aria
2 parents d24806e + 65fe71e commit 07a6180

File tree

5 files changed

+65
-19
lines changed

5 files changed

+65
-19
lines changed

app/assets/stylesheets/partials/_loading_spinner.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
}
99

1010
// Pagination overlay when loading
11-
[busy]:not([no-spinner]) {
11+
.spinner {
1212
position: relative;
1313
min-height: 400px;
1414
display: block;

app/helpers/search_helper.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,19 @@ def link_to_result(result)
2222
end
2323
end
2424

25+
def link_to_tab(target)
26+
if @active_tab == target.downcase
27+
link_to target, results_path(params.permit(:q, :per_page, :booleanType, :tab).merge(tab: target.downcase)),
28+
aria: { current: "page" },
29+
class: "active tab-link",
30+
data: { turbo_frame: "search-results", turbo_action: "advance" }
31+
else
32+
link_to target, results_path(params.permit(:q, :per_page, :booleanType, :tab).merge(tab: target.downcase)),
33+
class: "tab-link",
34+
data: { turbo_frame: "search-results", turbo_action: "advance" }
35+
end
36+
end
37+
2538
def view_online(result)
2639
return unless result[:source_link].present?
2740

app/javascript/loading_spinner.js

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
// Update the tab UI to reflect the newly-requested state. This function is called
2+
// by a click event handler in the tab UI. It follows a two-step process:
3+
function swapTabs(new_target) {
4+
// 1. Reset all tabs to base condition
5+
document.querySelectorAll('.tab-link').forEach((tab) => {
6+
tab.classList.remove('active');
7+
tab.removeAttribute('aria-current');
8+
});
9+
// 2. Add "active" class and aria-current attribute to the newly-active tab link
10+
const currentTabLink = document.querySelector(`.tab-link[href*="tab=${new_target}"]`);
11+
if (currentTabLink) {
12+
currentTabLink.classList.add('active');
13+
currentTabLink.setAttribute('aria-current', 'page');
14+
}
15+
}
16+
117
// Loading spinner behavior for pagination (Turbo Frame updates)
218
document.addEventListener('turbo:frame-render', function(event) {
319
if (window.pendingFocusAction === 'pagination') {
@@ -23,16 +39,8 @@ document.addEventListener('turbo:frame-render', function(event) {
2339
// console.log(`Updated tab input value to: ${queryParam}`);
2440
}
2541

26-
// update active tab styling
27-
// remove active class from all tabs
28-
document.querySelectorAll('.tab-link').forEach((tab) => {
29-
tab.classList.remove('active');
30-
});
31-
// add active class to current tab
32-
const currentTabLink = document.querySelector(`.tab-link[href*="tab=${queryParam}"]`);
33-
if (currentTabLink) {
34-
currentTabLink.classList.add('active');
35-
}
42+
// Remove the spinner now that things are ready
43+
document.getElementById('search-results').classList.remove('spinner');
3644

3745
// Clear the pending action
3846
window.pendingFocusAction = null;
@@ -51,7 +59,17 @@ document.addEventListener('click', function(event) {
5159

5260
// Handle tab clicks
5361
if (clickedElement.closest('.tab-navigation')) {
62+
const clickedParams = new URLSearchParams(clickedElement.search);
63+
const newTab = clickedParams.get('tab');
64+
65+
// Throw the spinner on the search results immediately
66+
document.getElementById('search-results').classList.add('spinner');
67+
68+
// Position the window at the top of the results
5469
window.scrollTo({ top: 0, behavior: 'smooth' });
70+
71+
swapTabs(newTab);
72+
5573
window.pendingFocusAction = 'tab';
5674
}
5775
});
Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
<!-- Tab Navigation -->
22
<nav id="tabs" class="tab-navigation" aria-label="Result type navigation">
33
<ul>
4-
<li>
5-
<%= link_to "Primo", results_path(params.permit(:q, :per_page, :booleanType, :tab).merge(tab: 'primo')),
6-
class: "tab-link #{'active' if @active_tab == 'primo'}",
7-
data: { turbo_frame: "search-results", turbo_action: "advance" } %></li>
8-
<li>
9-
<%= link_to "TIMDEX", results_path(params.permit(:q, :per_page, :booleanType, :tab).merge(tab: 'timdex')),
10-
class: "tab-link #{'active' if @active_tab == 'timdex'}",
11-
data: { turbo_frame: "search-results", turbo_action: "advance" } %></li>
4+
<li><%= link_to_tab("Primo") %></li>
5+
<li><%= link_to_tab("TIMDEX") %></li>
126
</ul>
137
</nav>
148

test/helpers/search_helper_test.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,27 @@ class SearchHelperTest < ActionView::TestCase
199199
assert_equal 'Sample Document Title', link_to_result(result)
200200
end
201201

202+
test 'link_to_tab builds a link without an aria attribute when that tab is not active' do
203+
@active_tab = 'bar'
204+
actual = link_to_tab('Foo')
205+
206+
assert_select Nokogiri::HTML::Document.parse( actual ), 'a' do |link|
207+
assert_select '[class*=?]', 'active', count: 0
208+
assert_select '[class*=?]', 'tab-link'
209+
assert_select '[aria-current=?]', 'page', count: 0
210+
end
211+
end
212+
213+
test 'link_to_tab builds a link that includes an aria attribute when that tab is active' do
214+
@active_tab = 'foo'
215+
actual = link_to_tab('Foo')
216+
217+
assert_select Nokogiri::HTML::Document.parse( actual ), 'a' do |link|
218+
assert_select link, '[class*=?]', 'active'
219+
assert_select link, '[aria-current=?]', 'page', count: 1
220+
end
221+
end
222+
202223
test 'primo_search_url generates correct Primo URL' do
203224
query = 'machine learning'
204225
expected_url = 'https://mit.primo.exlibrisgroup.com/discovery/search?query=any%2Ccontains%2Cmachine+learning&vid=01MIT_INST%3AMIT'

0 commit comments

Comments
 (0)