Skip to content

Commit 77ceb36

Browse files
authored
Merge pull request #3568 from projectblacklight/bl8-backport-facet-modal-fixes
[8.x] Backport facet modal bugfixes
2 parents fad722e + b56ff25 commit 77ceb36

File tree

12 files changed

+145
-45
lines changed

12 files changed

+145
-45
lines changed

app/assets/stylesheets/blacklight/_bootstrap_overrides.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,8 @@ dialog.modal[open] {
3939

4040
max-height: unset; // override user-agent dialog
4141
max-width: unset; // override user-agent dialog
42+
43+
&::backdrop {
44+
background-color: var(--bl-modal-backdrop-bg);
45+
}
4246
}

app/assets/stylesheets/blacklight/_facets.scss

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -207,12 +207,6 @@
207207
/* Sidenav
208208
-------------------------------------------------- */
209209

210-
.facet-pagination {
211-
&.top {
212-
padding: $modal-inner-padding;
213-
}
214-
}
215-
216210
.pivot-facet {
217211
&.show {
218212
display: flex;
@@ -272,3 +266,9 @@ $facet-toggle-height: $facet-toggle-width !default;
272266
$facet-toggle-width auto no-repeat;
273267
}
274268
}
269+
270+
/* Facet browse pages & modals
271+
-------------------------------------------------- */
272+
.facet-filters:not(:has(*)) {
273+
display: none !important;
274+
}

app/assets/stylesheets/blacklight/_modal.scss

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,26 @@
33
}
44

55
.modal-content {
6-
.facet-pagination.top {
7-
display: none;
8-
}
9-
106
.page-sidebar {
117
display: none;
128
}
139

1410
.blacklight-modal-close {
1511
display: block;
1612
}
17-
18-
.prev_next_links.btn-group .btn {
19-
border: 0;
20-
}
2113
}
2214

2315
// app/views/catalog/facet.html.erb may be rendered as a modal or a whole page.
2416
// When it's a whole page, don't show the close button.
2517
.blacklight-modal-close {
2618
display: none;
2719
}
20+
21+
// When modal content is rendered outside of a modal, Bootstrap css variables like
22+
// --bs-modal-footer-border-width are undefined (only in .modal scope). So we apply
23+
// light styling to the modal footer when it's not in a modal.
24+
.modal-footer:not(.modal .modal-footer) {
25+
border-top: var(--bs-border-width) solid var(--bs-border-color);
26+
padding-top: 1rem;
27+
margin-top: 1rem;
28+
}

app/assets/stylesheets/blacklight/_pagination.scss

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,5 @@
1010
}
1111

1212
.pagination {
13-
@media (max-width: breakpoint-max(sm)) {
14-
flex-wrap: wrap;
15-
}
13+
flex-wrap: wrap;
1614
}

app/assets/stylesheets/blacklight/blacklight_defaults.scss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,7 @@ $body-secondary-color: rgba($body-color, 0.75) !default;
2020
--bl-constraint-remove-hover-border-color: #bb2d3b;
2121

2222
--bl-field-name-color: var(--bs-secondary-color);
23+
24+
/* emulate Bootstrap backdrop bg & opacity */
25+
--bl-modal-backdrop-bg: rgba(0, 0, 0, 0.5);
2326
}

app/components/blacklight/facet_field_pagination_component.html.erb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<div class="prev_next_links btn-group">
22
<%= helpers.link_to_previous_page @facet_field.paginator, raw(t('views.pagination.previous')), params: @facet_field.search_state.to_h, param_name: param_name, class: 'btn btn-link', data: { blacklight_modal: "preserve" } do %>
3-
<%= content_tag :span, raw(t('views.pagination.previous')), class: 'disabled btn' %>
3+
<%= content_tag :a, raw(t('views.pagination.previous')), class: 'disabled btn btn-link text-decoration-none', aria: { disabled: true } %>
44
<% end %>
55

66
<%= helpers.link_to_next_page @facet_field.paginator, raw(t('views.pagination.next')), params: @facet_field.search_state.to_h, param_name: param_name, class: 'btn btn-link', data: { blacklight_modal: "preserve" } do %>
7-
<%= content_tag :span, raw(t('views.pagination.next')), class: 'disabled btn' %>
7+
<%= content_tag :a, raw(t('views.pagination.next')), class: 'disabled btn btn-link text-decoration-none', aria: { disabled: true } %>
88
<% end %>
99
</div>
1010

app/components/blacklight/search/facet_suggest_input.html.erb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
</label>
44
<%= text_field_tag "facet_suggest_#{facet.key}",
55
nil,
6-
class: "facet-suggest form-control",
7-
data: {facet_field: facet.key},
6+
class: "facet-suggest form-control mb-3",
7+
data: {
8+
facet_field: facet.key,
9+
facet_search_context: presenter.view_context.search_facet_path(id: facet.key)
10+
},
811
placeholder: I18n.t('blacklight.search.form.search.placeholder')
912
%>

app/javascript/blacklight/facet_suggest.js

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,42 @@ const FacetSuggest = async (e) => {
44
if (e.target.matches('.facet-suggest')) {
55
const queryFragment = e.target.value?.trim();
66
const facetField = e.target.dataset.facetField;
7+
const facetArea = document.querySelector('.facet-extended-list');
8+
const prevNextLinks = document.querySelectorAll('.prev_next_links');
9+
710
if (!facetField) { return; }
811

9-
const urlToFetch = `/catalog/facet_suggest/${facetField}/${queryFragment}${window.location.search}`
12+
// Get the search params from the current query so the facet suggestions
13+
// can retain that context.
14+
const facetSearchContext = e.target.dataset.facetSearchContext;
15+
const url = new URL(facetSearchContext, window.location.origin);
16+
17+
// Drop facet.page so a filtered suggestion list will always start on page 1
18+
url.searchParams.delete('facet.page');
19+
const facetSearchParams = url.searchParams.toString();
20+
21+
const urlToFetch = `/catalog/facet_suggest/${facetField}/${queryFragment}?${facetSearchParams}`;
22+
1023
const response = await fetch(urlToFetch);
1124
if (response.ok) {
1225
const blob = await response.blob()
1326
const text = await blob.text()
14-
27+
1528
const facetArea = document.querySelector('.facet-extended-list');
16-
29+
1730
if (text && facetArea) {
1831
facetArea.innerHTML = text
1932
}
2033
}
34+
35+
// Hide the prev/next links when a user enters text in the facet
36+
// suggestion input. They don't work with a filtered list.
37+
prevNextLinks.forEach(element => {
38+
element.classList.toggle('invisible', !!queryFragment);
39+
});
40+
41+
// Add a class to distinguish suggested facet values vs. regular.
42+
facetArea.classList.toggle('facet-suggestions', !!queryFragment);
2143
}
2244
};
2345

app/views/catalog/facet.html.erb

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
<%= render Blacklight::System::ModalComponent.new do |component| %>
2-
<% component.with_prefix do %>
3-
<div class="facet-pagination top row justify-content-between">
4-
<%= render :partial=>'facet_pagination' %>
5-
</div>
6-
<% end %>
7-
82
<% component.with_title { facet_field_label(@facet.key) } %>
9-
<%= render Blacklight::Search::FacetSuggestInput.new(facet: @facet, presenter: @presenter) %>
103

11-
<%= render partial: 'facet_index_navigation' if @facet.index_range && @display_facet.index? %>
4+
<div class="facet-filters card card-body bg-light p-3 mb-3 border-0">
5+
<%= render Blacklight::Search::FacetSuggestInput.new(facet: @facet, presenter: @presenter) %>
6+
<%= render partial: 'facet_index_navigation' if @facet.index_range && @display_facet.index? %>
7+
</div>
8+
9+
<div class="facet-pagination top d-flex flex-wrap w-100 justify-content-between border-bottom pb-3 mb-3">
10+
<%= render :partial=>'facet_pagination' %>
11+
</div>
1212

1313
<div class="facet-extended-list">
1414
<%= render Blacklight::FacetComponent.new(display_facet: @display_facet,
@@ -17,7 +17,7 @@
1717
</div>
1818

1919
<% component.with_footer do %>
20-
<div class="facet-pagination bottom flex-row justify-content-between">
20+
<div class="facet-pagination bottom d-flex flex-wrap w-100 justify-content-between">
2121
<%= render :partial=>'facet_pagination' %>
2222
</div>
2323
<% end %>

spec/components/blacklight/search/facet_suggest_input_spec.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
RSpec.describe Blacklight::Search::FacetSuggestInput, type: :component do
66
let(:facet) { Blacklight::Configuration::FacetField.new key: 'language_facet', suggest: true }
77
let(:presenter) { instance_double(Blacklight::FacetFieldPresenter) }
8+
let(:view_context) { double(ActionView::Base) }
89

910
before do
10-
allow(presenter).to receive(:label).and_return 'Language'
11+
allow(presenter).to receive_messages(label: 'Language', view_context: view_context)
12+
allow(view_context).to receive(:search_facet_path).and_return('/catalog/facet/language_facet')
1113
end
1214

1315
it 'has an input with the facet-suggest class, which the javascript needs to find it' do
@@ -20,6 +22,12 @@
2022
expect(rendered.css('input[data-facet-field="language_facet"]').count).to eq 1
2123
end
2224

25+
it 'has an input with the data-facet-search-context attribute, which the javascript needs to determine the current search context' do
26+
allow(view_context).to receive(:search_facet_path).and_return('/catalog/facet/language_facet?f%5Bformat%5D%5B%5D=Book&facet.prefix=R&facet.sort=index&q=tibet&search_field=all_fields')
27+
rendered = render_inline(described_class.new(facet: facet, presenter: presenter))
28+
expect(rendered.css('input[data-facet-search-context="/catalog/facet/language_facet?f%5Bformat%5D%5B%5D=Book&facet.prefix=R&facet.sort=index&q=tibet&search_field=all_fields"]').count).to eq 1
29+
end
30+
2331
it 'has a visible label that is associated with the input' do
2432
rendered = render_inline(described_class.new(facet: facet, presenter: presenter))
2533
label = rendered.css('label').first

0 commit comments

Comments
 (0)