Skip to content

Commit 3b1e1fd

Browse files
committed
Update pagination buttons to include results count
Why are these changes being introduced: * UX design includes showing the number of results that will be shown when clicking the Next or Previous pagination buttons. * Previous page should always be the same number of results as per_page so it is simpler to say "Previous 20 results" rather than trying to calculate how many results remain before the start index. * Next page should show the remaining results if fewer than per_page results remain. * Also introduces a disabled state via a span for the next and previous buttons when there are no more results in that direction. Relevant ticket(s): * https://mitlibraries.atlassian.net/browse/USE-184 How does this address that need: * Mathed out the new pagination button text requirements * Updated PaginationHelper methods to calculate remaining results * Updated PaginationHelper methods to render disabled span when no more results in that direction
1 parent dba03f9 commit 3b1e1fd

File tree

4 files changed

+98
-52
lines changed

4 files changed

+98
-52
lines changed

app/helpers/pagination_helper.rb

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,16 @@ def first_url(query_params)
77
# Preserve the active tab in pagination URLs.
88
params_copy[:tab] = @active_tab if @active_tab.present?
99

10-
link_to results_path(params_copy), 'aria-label': 'First page',
11-
data: { turbo_frame: 'search-results', turbo_action: 'advance' },
12-
rel: 'nofollow' do
13-
'«« First'.html_safe
10+
# First page gets a disabled link in a span
11+
# Check the original, not copied params to determine if we need a disabled link
12+
if query_params[:page].blank? || query_params[:page].to_i == 1
13+
'<span role="link" aria-disabled="true" tabindex="-1">First</span>'.html_safe
14+
else
15+
link_to results_path(params_copy), 'aria-label': 'First',
16+
data: { turbo_frame: 'search-results', turbo_action: 'advance' },
17+
rel: 'nofollow' do
18+
'First'.html_safe
19+
end
1420
end
1521
end
1622

@@ -22,13 +28,32 @@ def next_url(query_params)
2228
# Preserve the active tab in pagination URLs.
2329
params_copy[:tab] = @active_tab if @active_tab.present?
2430

25-
link_to results_path(params_copy), 'aria-label': 'Next page',
26-
data: { turbo_frame: 'search-results', turbo_action: 'advance' },
27-
rel: 'nofollow' do
28-
'Next &raquo;'.html_safe
31+
if remaining_results <= 0
32+
"<span role='link' aria-disabled='true' tabindex='-1'>#{next_page_label}</span>".html_safe
33+
else
34+
link_to results_path(params_copy), 'aria-label': next_page_label,
35+
data: { turbo_frame: 'search-results', turbo_action: 'advance' },
36+
rel: 'nofollow' do
37+
next_page_label.html_safe
38+
end
2939
end
3040
end
3141

42+
# Calculate how many results remain after the current end index
43+
def remaining_results
44+
@pagination[:hits] - @pagination[:end]
45+
end
46+
47+
def next_page_label
48+
label = if (@pagination[:end] + @pagination[:per_page]) < @pagination[:hits]
49+
@pagination[:per_page]
50+
else
51+
remaining_results
52+
end
53+
54+
"Next #{label} results"
55+
end
56+
3257
def prev_url(query_params)
3358
# Work with a copy to avoid mutating the original enhanced_query.
3459
params_copy = query_params.dup
@@ -37,10 +62,19 @@ def prev_url(query_params)
3762
# Preserve the active tab in pagination URLs.
3863
params_copy[:tab] = @active_tab if @active_tab.present?
3964

40-
link_to results_path(params_copy), 'aria-label': 'Previous page',
41-
data: { turbo_frame: 'search-results', turbo_action: 'advance' },
42-
rel: 'nofollow' do
43-
'&laquo; Previous'.html_safe
65+
# First page gets a disabled link in a span
66+
if query_params[:page].blank? || query_params[:page].to_i == 1
67+
"<span role='link' aria-disabled='true' tabindex='-1'>#{prev_page_label}</span>".html_safe
68+
else
69+
link_to results_path(params_copy), 'aria-label': prev_page_label,
70+
data: { turbo_frame: 'search-results', turbo_action: 'advance' },
71+
rel: 'nofollow' do
72+
prev_page_label.html_safe
73+
end
4474
end
4575
end
76+
77+
def prev_page_label
78+
'Previous 20 results'
79+
end
4680
end

app/models/analyzer.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@ def initialize(enhanced_query, response, source)
1515
@pagination[:start] = ((enhanced_query[:page] - 1) * RESULTS_PER_PAGE) + 1
1616
@pagination[:end] = [enhanced_query[:page] * RESULTS_PER_PAGE, @pagination[:hits]].min
1717
@pagination[:prev] = enhanced_query[:page] - 1 if enhanced_query[:page] > 1
18-
19-
next_page_num = next_page(enhanced_query[:page], @pagination[:hits])
20-
@pagination[:next] = next_page_num if next_page_num
18+
@pagination[:next] = next_page(enhanced_query[:page], @pagination[:hits]) if next_page(
19+
enhanced_query[:page], @pagination[:hits]
20+
)
21+
@pagination[:per_page] = RESULTS_PER_PAGE
2122
end
2223

2324
private

app/views/search/_pagination.html.erb

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,13 @@
22

33
<nav class="pagination-container" aria-label="Pagination">
44
<div class="first">
5-
<% current_page = @enhanced_query[:page] || 1 %>
6-
<% if current_page > 2 %>
7-
<%= first_url(@enhanced_query) %>
8-
<% else %>
9-
First
10-
<% end %>
5+
<%= first_url(@enhanced_query) %>
116
</div>
127
<div class="previous">
13-
<% if @pagination[:prev] %>
14-
<%= prev_url(@enhanced_query) %>
15-
<% else %>
16-
Previous
17-
<% end %>
8+
<%= prev_url(@enhanced_query) %>
189
</div>
1910
<div class="current"><%= @pagination[:start] %> - <%= @pagination[:end] %> of <%= number_with_delimiter(@pagination[:hits]) %></div>
2011
<div class="next">
21-
<% if @pagination[:next] %>
22-
<%= next_url(@enhanced_query) %>
23-
<% else %>
24-
Last
25-
<% end %>
12+
<%= next_url(@enhanced_query) %>
2613
</div>
2714
</nav>

test/helpers/pagination_helper_test.rb

Lines changed: 45 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,69 +4,93 @@ class PaginationHelperTest < ActionView::TestCase
44
include PaginationHelper
55

66
test 'Next links for basic search' do
7-
@pagination = { next: 12 }
8-
query_params = { q: 'popcorn' }
7+
@pagination = { prev: 11, next: 13, per_page: 20, hits: 1000, end: 260 }
8+
query_params = { q: 'popcorn', page: 12 }
99
assert_equal(
10-
'<a aria-label="Next page" data-turbo-frame="search-results" data-turbo-action="advance" rel="nofollow" href="/results?page=12&amp;q=popcorn">Next &raquo;</a>', next_url(query_params)
10+
'<a aria-label="Next 20 results" data-turbo-frame="search-results" data-turbo-action="advance" rel="nofollow" href="/results?page=13&amp;q=popcorn">Next 20 results</a>', next_url(query_params)
1111
)
1212
end
1313

1414
test 'Next links for advanced search' do
15-
@pagination = { next: 12 }
15+
@pagination = { prev: 11, next: 13, per_page: 20, hits: 1000, end: 260 }
1616
query_params = { q: 'popcorn', title: 'titles are cool', contributors: 'yawn' }
1717
assert_equal(
18-
'<a aria-label="Next page" data-turbo-frame="search-results" data-turbo-action="advance" rel="nofollow" href="/results?contributors=yawn&amp;page=12&amp;q=popcorn&amp;title=titles+are+cool">Next &raquo;</a>',
18+
'<a aria-label="Next 20 results" data-turbo-frame="search-results" data-turbo-action="advance" rel="nofollow" href="/results?contributors=yawn&amp;page=13&amp;q=popcorn&amp;title=titles+are+cool">Next 20 results</a>',
1919
next_url(query_params)
2020
)
2121
end
2222

2323
test 'Previous links for basic search' do
24-
@pagination = { prev: 11 }
25-
query_params = { q: 'popcorn' }
24+
@pagination = { prev: 11, next: 13, per_page: 20, hits: 1000, end: 260 }
25+
query_params = { q: 'popcorn', page: 12 }
2626
assert_equal(
27-
'<a aria-label="Previous page" data-turbo-frame="search-results" data-turbo-action="advance" rel="nofollow" href="/results?page=11&amp;q=popcorn">&laquo; Previous</a>', prev_url(query_params)
27+
'<a aria-label="Previous 20 results" data-turbo-frame="search-results" data-turbo-action="advance" rel="nofollow" href="/results?page=11&amp;q=popcorn">Previous 20 results</a>', prev_url(query_params)
2828
)
2929
end
3030

3131
test 'Previous links for advanced search' do
32-
@pagination = { prev: 11 }
33-
query_params = { q: 'popcorn', title: 'titles are cool', contributors: 'yawn' }
32+
@pagination = { prev: 11, next: 13, per_page: 20, hits: 1000, end: 260 }
33+
query_params = { q: 'popcorn', title: 'titles are cool', contributors: 'yawn', page: 12 }
3434
assert_equal(
35-
'<a aria-label="Previous page" data-turbo-frame="search-results" data-turbo-action="advance" rel="nofollow" href="/results?contributors=yawn&amp;page=11&amp;q=popcorn&amp;title=titles+are+cool">&laquo; Previous</a>',
35+
'<a aria-label="Previous 20 results" data-turbo-frame="search-results" data-turbo-action="advance" rel="nofollow" href="/results?contributors=yawn&amp;page=11&amp;q=popcorn&amp;title=titles+are+cool">Previous 20 results</a>',
3636
prev_url(query_params)
3737
)
3838
end
3939

4040
test 'Next links preserve active tab' do
41-
@pagination = { next: 12 }
41+
@pagination = { prev: 11, next: 13, per_page: 20, hits: 1000, end: 260 }
4242
@active_tab = 'primo'
43-
query_params = { q: 'popcorn' }
43+
query_params = { q: 'popcorn', page: 12 }
4444
assert_equal(
45-
'<a aria-label="Next page" data-turbo-frame="search-results" data-turbo-action="advance" rel="nofollow" href="/results?page=12&amp;q=popcorn&amp;tab=primo">Next &raquo;</a>', next_url(query_params)
45+
'<a aria-label="Next 20 results" data-turbo-frame="search-results" data-turbo-action="advance" rel="nofollow" href="/results?page=13&amp;q=popcorn&amp;tab=primo">Next 20 results</a>', next_url(query_params)
4646
)
4747
end
4848

4949
test 'Previous links preserve active tab' do
50-
@pagination = { prev: 11 }
50+
@pagination = { prev: 11, next: 13, per_page: 20, hits: 1000, end: 260 }
5151
@active_tab = 'timdex'
52-
query_params = { q: 'popcorn' }
52+
query_params = { q: 'popcorn', page: 12 }
5353
assert_equal(
54-
'<a aria-label="Previous page" data-turbo-frame="search-results" data-turbo-action="advance" rel="nofollow" href="/results?page=11&amp;q=popcorn&amp;tab=timdex">&laquo; Previous</a>', prev_url(query_params)
54+
'<a aria-label="Previous 20 results" data-turbo-frame="search-results" data-turbo-action="advance" rel="nofollow" href="/results?page=11&amp;q=popcorn&amp;tab=timdex">Previous 20 results</a>', prev_url(query_params)
5555
)
5656
end
5757

58-
test 'First links for basic search' do
58+
test 'First links for initial basic search is disabled' do
5959
query_params = { q: 'popcorn' }
6060
assert_equal(
61-
'<a aria-label="First page" data-turbo-frame="search-results" data-turbo-action="advance" rel="nofollow" href="/results?page=1&amp;q=popcorn">&laquo;&laquo; First</a>', first_url(query_params)
61+
'<span role="link" aria-disabled="true" tabindex="-1">First</span>', first_url(query_params)
6262
)
6363
end
6464

6565
test 'First links preserve active tab' do
6666
@active_tab = 'primo'
67-
query_params = { q: 'popcorn' }
67+
query_params = { q: 'popcorn', page: 5 }
68+
assert_equal(
69+
'<a aria-label="First" data-turbo-frame="search-results" data-turbo-action="advance" rel="nofollow" href="/results?page=1&amp;q=popcorn&amp;tab=primo">First</a>', first_url(query_params)
70+
)
71+
end
72+
73+
test 'Next link for penultimate page is correct' do
74+
@pagination = { next: 6, per_page: 20, hits: 102, end: 100 }
75+
query_params = { q: 'popcorn', page: 5 }
76+
assert_equal(
77+
'<a aria-label="Next 2 results" data-turbo-frame="search-results" data-turbo-action="advance" rel="nofollow" href="/results?page=6&amp;q=popcorn">Next 2 results</a>', next_url(query_params)
78+
)
79+
end
80+
81+
test 'Next link for full last page is disabled' do
82+
@pagination = { next: 6, per_page: 20, hits: 100, end: 100 }
83+
query_params = { q: 'popcorn', page: 5 }
84+
assert_equal(
85+
"<span role='link' aria-disabled='true' tabindex='-1'>Next 0 results</span>", next_url(query_params)
86+
)
87+
end
88+
89+
test 'Previous link for first page is disabled' do
90+
@pagination = { prev: nil, per_page: 20, hits: 100, end: 20 }
91+
query_params = { q: 'popcorn', page: 1 }
6892
assert_equal(
69-
'<a aria-label="First page" data-turbo-frame="search-results" data-turbo-action="advance" rel="nofollow" href="/results?page=1&amp;q=popcorn&amp;tab=primo">&laquo;&laquo; First</a>', first_url(query_params)
93+
"<span role='link' aria-disabled='true' tabindex='-1'>Previous 20 results</span>", prev_url(query_params)
7094
)
7195
end
7296
end

0 commit comments

Comments
 (0)