blacklight 7.1.0 → 7.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.jshintrc +3 -1
- data/.rubocop_todo.yml +8 -8
- data/.travis.yml +13 -13
- data/CONTRIBUTING.md +3 -1
- data/Gemfile +2 -0
- data/VERSION +1 -1
- data/app/assets/images/blacklight/list.svg +1 -1
- data/app/assets/images/blacklight/search.svg +1 -1
- data/app/assets/javascripts/blacklight/blacklight.js +82 -70
- data/app/assets/stylesheets/blacklight/_bootstrap_overrides.scss +17 -13
- data/app/assets/stylesheets/blacklight/_facets.scss +3 -0
- data/app/assets/stylesheets/blacklight/_header.scss +26 -0
- data/app/assets/stylesheets/blacklight/_icons.scss +6 -6
- data/app/assets/stylesheets/blacklight/_mixins.scss +3 -3
- data/app/controllers/concerns/blacklight/facet.rb +1 -7
- data/app/helpers/blacklight/catalog_helper_behavior.rb +16 -17
- data/app/helpers/blacklight/layout_helper_behavior.rb +2 -2
- data/app/helpers/blacklight/url_helper_behavior.rb +1 -1
- data/app/javascript/blacklight/button_focus.js +9 -0
- data/app/javascript/blacklight/facet_load.js +18 -19
- data/app/javascript/blacklight/search_context.js +67 -49
- data/app/models/blacklight/icon.rb +26 -5
- data/app/presenters/blacklight/search_bar_presenter.rb +3 -1
- data/app/views/catalog/_bookmark_control.html.erb +11 -13
- data/app/views/catalog/_facet_group.html.erb +1 -1
- data/app/views/catalog/_facet_layout.html.erb +9 -2
- data/app/views/catalog/_facets.html.erb +1 -1
- data/app/views/catalog/_per_page_widget.html.erb +1 -1
- data/app/views/catalog/_search_form.html.erb +1 -1
- data/app/views/catalog/_search_results.html.erb +4 -0
- data/app/views/catalog/_sort_widget.html.erb +1 -1
- data/app/views/layouts/blacklight.html.erb +2 -2
- data/app/views/layouts/blacklight/base.html.erb +14 -8
- data/config/locales/blacklight.de.yml +17 -2
- data/config/locales/blacklight.en.yml +17 -2
- data/config/locales/blacklight.es.yml +17 -2
- data/config/locales/blacklight.fr.yml +17 -2
- data/config/locales/blacklight.hu.yml +17 -3
- data/config/locales/blacklight.it.yml +17 -2
- data/config/locales/blacklight.nl.yml +17 -3
- data/config/locales/blacklight.pt-BR.yml +17 -2
- data/config/locales/blacklight.sq.yml +17 -2
- data/config/locales/blacklight.zh.yml +17 -3
- data/lib/blacklight/configuration.rb +6 -0
- data/lib/blacklight/engine.rb +5 -4
- data/lib/blacklight/solr.rb +2 -0
- data/{app/models/concerns → lib}/blacklight/solr/document.rb +0 -0
- data/{app/models → lib}/blacklight/solr/facet_paginator.rb +0 -0
- data/lib/blacklight/solr/response/group_response.rb +10 -0
- data/lib/blacklight/solr/response/pagination_methods.rb +12 -0
- data/lib/generators/blacklight/assets_generator.rb +4 -1
- data/package-lock.json +1 -1
- data/package.json +2 -2
- data/spec/features/facets_spec.rb +22 -1
- data/spec/features/search_filters_spec.rb +25 -5
- data/spec/helpers/blacklight/layout_helper_behavior_spec.rb +4 -4
- data/spec/helpers/catalog_helper_spec.rb +0 -9
- data/spec/models/blacklight/icon_spec.rb +25 -1
- data/spec/models/blacklight/solr/response/group_response_spec.rb +13 -0
- data/spec/models/blacklight/solr/response_spec.rb +3 -0
- data/spec/presenters/blacklight/search_bar_presenter_spec.rb +15 -0
- data/spec/views/catalog/_facet_group.html.erb_spec.rb +82 -0
- data/spec/views/catalog/_facet_layout.html.erb_spec.rb +1 -1
- data/spec/views/catalog/_facets.html.erb_spec.rb +5 -66
- metadata +7 -5
- data/app/javascript/blacklight/collapsable.js +0 -9
@@ -13,22 +13,22 @@
|
|
13
13
|
|
14
14
|
@each $color, $value in $theme-colors {
|
15
15
|
.btn-#{$color} {
|
16
|
-
.blacklight-icons
|
17
|
-
@include
|
16
|
+
.blacklight-icons svg {
|
17
|
+
@include fill-yiq(theme-color($color));
|
18
18
|
}
|
19
19
|
}
|
20
20
|
|
21
21
|
.btn-outline-#{$color} {
|
22
|
-
.blacklight-icons
|
23
|
-
|
22
|
+
.blacklight-icons svg {
|
23
|
+
fill: $value;
|
24
24
|
}
|
25
25
|
|
26
26
|
&.hover,
|
27
27
|
&:hover,
|
28
28
|
&:active,
|
29
29
|
&.active {
|
30
|
-
.blacklight-icons
|
31
|
-
@include
|
30
|
+
.blacklight-icons svg {
|
31
|
+
@include fill-yiq(theme-color($color));
|
32
32
|
}
|
33
33
|
}
|
34
34
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
// Stroke contrast
|
2
2
|
// Ripped off from https://github.com/twbs/bootstrap/commit/c31d52499811d5c68d122db806ce27a112b489bd
|
3
|
-
@mixin
|
3
|
+
@mixin fill-yiq($color) {
|
4
4
|
$r: red($color);
|
5
5
|
$g: green($color);
|
6
6
|
$b: blue($color);
|
@@ -8,8 +8,8 @@
|
|
8
8
|
$yiq: (($r * 299) + ($g * 587) + ($b * 114)) / 1000;
|
9
9
|
|
10
10
|
@if ($yiq >= 150) {
|
11
|
-
|
11
|
+
fill: #111;
|
12
12
|
} @else {
|
13
|
-
|
13
|
+
fill: #fff;
|
14
14
|
}
|
15
15
|
}
|
@@ -4,7 +4,7 @@ module Blacklight
|
|
4
4
|
# They are only dependent on `blacklight_config` and `@response`
|
5
5
|
#
|
6
6
|
module Facet
|
7
|
-
delegate :facet_configuration_for_field, to: :blacklight_config
|
7
|
+
delegate :facet_configuration_for_field, :facet_field_names, to: :blacklight_config
|
8
8
|
|
9
9
|
def facet_paginator(field_config, response_data)
|
10
10
|
blacklight_config.facet_paginator_class.new(
|
@@ -22,12 +22,6 @@ module Blacklight
|
|
22
22
|
fields.map { |field| facet_by_field_name(field) }.compact
|
23
23
|
end
|
24
24
|
|
25
|
-
# @param group [String] a group name of facet fields
|
26
|
-
# @return [Array<String>] a list of the facet field names from the configuration
|
27
|
-
def facet_field_names(group = nil)
|
28
|
-
blacklight_config.facet_fields.select { |_facet, opts| group == opts[:group] }.values.map(&:field)
|
29
|
-
end
|
30
|
-
|
31
25
|
def facet_group_names
|
32
26
|
blacklight_config.facet_fields.map { |_facet, opts| opts[:group] }.uniq
|
33
27
|
end
|
@@ -3,13 +3,13 @@ module Blacklight::CatalogHelperBehavior
|
|
3
3
|
extend Deprecation
|
4
4
|
self.deprecation_horizon = 'blacklight 8.0'
|
5
5
|
|
6
|
-
include ConfigurationHelperBehavior
|
7
|
-
include ComponentHelperBehavior
|
8
|
-
include FacetsHelperBehavior
|
9
|
-
include RenderConstraintsHelperBehavior
|
10
|
-
include RenderPartialsHelperBehavior
|
11
|
-
include SearchHistoryConstraintsHelperBehavior
|
12
|
-
include SuggestHelperBehavior
|
6
|
+
include Blacklight::ConfigurationHelperBehavior
|
7
|
+
include Blacklight::ComponentHelperBehavior
|
8
|
+
include Blacklight::FacetsHelperBehavior
|
9
|
+
include Blacklight::RenderConstraintsHelperBehavior
|
10
|
+
include Blacklight::RenderPartialsHelperBehavior
|
11
|
+
include Blacklight::SearchHistoryConstraintsHelperBehavior
|
12
|
+
include Blacklight::SuggestHelperBehavior
|
13
13
|
|
14
14
|
# @param [Hash] options
|
15
15
|
# @option options :route_set the route scope to use when constructing the link
|
@@ -31,22 +31,21 @@ module Blacklight::CatalogHelperBehavior
|
|
31
31
|
|
32
32
|
##
|
33
33
|
# Override the Kaminari page_entries_info helper with our own, blacklight-aware
|
34
|
-
# implementation.
|
35
|
-
#
|
34
|
+
# implementation. Why do we have to do this?
|
35
|
+
# - We need custom counting information for grouped results
|
36
|
+
# - We need to provide number_with_delimiter strings to i18n keys
|
37
|
+
# If we didn't have to do either one of these, we could get away with removing
|
38
|
+
# this entirely.
|
36
39
|
#
|
37
40
|
# @param [RSolr::Resource] collection (or other Kaminari-compatible objects)
|
38
41
|
# @return [String]
|
39
|
-
def page_entries_info(collection,
|
42
|
+
def page_entries_info(collection, entry_name: nil)
|
40
43
|
return unless show_pagination? collection
|
41
44
|
|
42
|
-
entry_name = if
|
43
|
-
|
44
|
-
elsif collection.respond_to? :model # DataMapper
|
45
|
-
collection.model.model_name.human.downcase
|
46
|
-
elsif collection.respond_to?(:model_name) && !collection.model_name.nil? # AR, Blacklight::PaginationMethods
|
47
|
-
collection.model_name.human.downcase
|
45
|
+
entry_name = if entry_name
|
46
|
+
entry_name.pluralize(collection.size, I18n.locale)
|
48
47
|
else
|
49
|
-
|
48
|
+
collection.entry_name(count: collection.size).downcase
|
50
49
|
end
|
51
50
|
|
52
51
|
entry_name = entry_name.pluralize unless collection.total_count == 1
|
@@ -22,14 +22,14 @@ module Blacklight
|
|
22
22
|
# Classes used for sizing the main content of a Blacklight page
|
23
23
|
# @return [String]
|
24
24
|
def main_content_classes
|
25
|
-
'col-
|
25
|
+
'col-lg-9'
|
26
26
|
end
|
27
27
|
|
28
28
|
##
|
29
29
|
# Classes used for sizing the sidebar content of a Blacklight page
|
30
30
|
# @return [String]
|
31
31
|
def sidebar_classes
|
32
|
-
'page-sidebar col-
|
32
|
+
'page-sidebar col-lg-3'
|
33
33
|
end
|
34
34
|
|
35
35
|
##
|
@@ -66,7 +66,7 @@ module Blacklight::UrlHelperBehavior
|
|
66
66
|
# @param [Integer] counter
|
67
67
|
# @example
|
68
68
|
# session_tracking_params(SolrDocument.new(id: 123), 7)
|
69
|
-
# => { data: { :'
|
69
|
+
# => { data: { :'context-href' => '/catalog/123/track?counter=7&search_id=999' } }
|
70
70
|
def session_tracking_params document, counter
|
71
71
|
path = session_tracking_path(document, per_page: params.fetch(:per_page, search_session['per_page']), counter: counter, search_id: current_search_session.try(:id))
|
72
72
|
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Blacklight.onLoad(function() {
|
2
|
+
// Button clicks should change focus. As of 10/3/19, Firefox for Mac and
|
3
|
+
// Safari both do not set focus to a button on button click.
|
4
|
+
document.querySelectorAll('button.collapse-toggle').forEach((button) => {
|
5
|
+
button.addEventListener('click', () => {
|
6
|
+
event.target.focus();
|
7
|
+
});
|
8
|
+
});
|
9
|
+
});
|
@@ -1,23 +1,22 @@
|
|
1
1
|
/*global Blacklight */
|
2
2
|
|
3
|
-
|
4
|
-
'use strict';
|
5
|
-
|
6
|
-
Blacklight.doResizeFacetLabelsAndCounts = function() {
|
7
|
-
// adjust width of facet columns to fit their contents
|
8
|
-
function longer (a,b){ return b.textContent.length - a.textContent.length; }
|
3
|
+
'use strict';
|
9
4
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
if (longest && longest.textContent) {
|
14
|
-
var width = longest.textContent.length + 1 + 'ch';
|
15
|
-
$(this).find('.facet-count').first().width(width);
|
16
|
-
}
|
17
|
-
});
|
18
|
-
};
|
5
|
+
Blacklight.doResizeFacetLabelsAndCounts = function() {
|
6
|
+
// adjust width of facet columns to fit their contents
|
7
|
+
function longer (a,b) { return b.textContent.length - a.textContent.length }
|
19
8
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
9
|
+
document.querySelectorAll('.facet-values, .pivot-facet').forEach(function(elem){
|
10
|
+
const nodes = elem.querySelectorAll('.facet-count')
|
11
|
+
// TODO: when we drop ie11 support, this can become the spread operator:
|
12
|
+
const longest = Array.from(nodes).sort(longer)[0]
|
13
|
+
if (longest && longest.textContent) {
|
14
|
+
const width = longest.textContent.length + 1 + 'ch'
|
15
|
+
elem.querySelector('.facet-count').style.width = width
|
16
|
+
}
|
17
|
+
})
|
18
|
+
}
|
19
|
+
|
20
|
+
Blacklight.onLoad(function() {
|
21
|
+
Blacklight.doResizeFacetLabelsAndCounts()
|
22
|
+
})
|
@@ -1,49 +1,67 @@
|
|
1
|
-
|
2
|
-
Blacklight.
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
1
|
+
Blacklight.doSearchContextBehavior = function() {
|
2
|
+
if (typeof Blacklight.do_search_context_behavior == 'function') {
|
3
|
+
console.warn("do_search_context_behavior is deprecated. Use doSearchContextBehavior instead.");
|
4
|
+
return Blacklight.do_search_context_behavior();
|
5
|
+
}
|
6
|
+
|
7
|
+
const elements = document.querySelectorAll('a[data-context-href]')
|
8
|
+
// Equivalent to Array.from(), but supports ie11
|
9
|
+
const nodes = Array.prototype.slice.call(elements)
|
10
|
+
|
11
|
+
nodes.forEach(function(element) {
|
12
|
+
element.addEventListener('click', function(e) {
|
13
|
+
Blacklight.handleSearchContextMethod.call(e.target, e)
|
14
|
+
})
|
15
|
+
})
|
16
|
+
};
|
17
|
+
|
18
|
+
// this is the Rails.handleMethod with a couple adjustments, described inline:
|
19
|
+
// first, we're attaching this directly to the event handler, so we can check for meta-keys
|
20
|
+
Blacklight.handleSearchContextMethod = function(event) {
|
21
|
+
if (typeof Blacklight.handle_search_context_method == 'function') {
|
22
|
+
console.warn("handle_search_context_method is deprecated. Use handleSearchContextMethod instead.");
|
23
|
+
return Blacklight.handle_search_context_method(event);
|
24
|
+
}
|
25
|
+
var link = this
|
26
|
+
|
27
|
+
// instead of using the normal href, we need to use the context href instead
|
28
|
+
let href = link.getAttribute('data-context-href')
|
29
|
+
let target = link.getAttribute('target')
|
30
|
+
let csrfToken = Rails.csrfToken()
|
31
|
+
let csrfParam = Rails.csrfParam()
|
32
|
+
let form = document.createElement('form')
|
33
|
+
form.method = 'post'
|
34
|
+
form.action = href
|
35
|
+
|
36
|
+
|
37
|
+
let formContent = `<input name="_method" value="post" type="hidden" />
|
38
|
+
<input name="redirect" value="${link.getAttribute('href')}" type="hidden" />`
|
39
|
+
|
40
|
+
// check for meta keys.. if set, we should open in a new tab
|
41
|
+
if(event.metaKey || event.ctrlKey) {
|
42
|
+
target = '_blank';
|
43
|
+
}
|
44
|
+
|
45
|
+
if (csrfParam !== undefined && csrfToken !== undefined) {
|
46
|
+
formContent += `<input name="${csrfParam}" value="${csrfToken}" type="hidden" />`
|
47
|
+
}
|
48
|
+
|
49
|
+
// Must trigger submit by click on a button, else "submit" event handler won't work!
|
50
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit
|
51
|
+
formContent += '<input type="submit" />'
|
52
|
+
|
53
|
+
if (target) { form.setAttribute('target', target); }
|
54
|
+
|
55
|
+
form.style.display = 'none'
|
56
|
+
form.innerHTML = formContent
|
57
|
+
document.body.appendChild(form)
|
58
|
+
form.querySelector('[type="submit"]').click()
|
59
|
+
|
60
|
+
event.preventDefault()
|
61
|
+
event.stopPropagation()
|
62
|
+
event.stopImmediatePropagation()
|
63
|
+
};
|
64
|
+
|
65
|
+
Blacklight.onLoad(function() {
|
66
|
+
Blacklight.doSearchContextBehavior();
|
67
|
+
});
|
@@ -2,22 +2,39 @@
|
|
2
2
|
|
3
3
|
module Blacklight
|
4
4
|
class Icon
|
5
|
-
attr_reader :icon_name
|
5
|
+
attr_reader :icon_name, :aria_hidden, :label, :role
|
6
6
|
##
|
7
7
|
# @param [String, Symbol] icon_name
|
8
8
|
# @param [Hash] options
|
9
9
|
# @param [String] classes additional classes separated by a string
|
10
|
-
|
10
|
+
# @param [Boolean] aria_hidden include aria_hidden attribute
|
11
|
+
# @param [Boolean] label include <title> and aria-label as part of svg
|
12
|
+
# @param [String] role role attribute to be included in svg
|
13
|
+
def initialize(icon_name, classes: '', aria_hidden: false, label: true, role: 'image')
|
11
14
|
@icon_name = icon_name
|
12
15
|
@classes = classes
|
13
16
|
@aria_hidden = aria_hidden
|
17
|
+
@label = label
|
18
|
+
@role = role
|
14
19
|
end
|
15
20
|
|
16
21
|
##
|
17
|
-
# Returns
|
22
|
+
# Returns an updated version of the svg source
|
18
23
|
# @return [String]
|
19
24
|
def svg
|
20
|
-
|
25
|
+
svg = ng_xml.at_xpath('svg')
|
26
|
+
svg['role'] = role
|
27
|
+
svg['aria-labelled-by'] = unique_id if label
|
28
|
+
svg.add_child("<title id='#{unique_id}'>#{icon_label}</title>") if label
|
29
|
+
ng_xml.to_xml
|
30
|
+
end
|
31
|
+
|
32
|
+
def icon_label
|
33
|
+
I18n.translate("blacklight.icon.#{icon_name}", default: "#{icon_name} icon")
|
34
|
+
end
|
35
|
+
|
36
|
+
def unique_id
|
37
|
+
@unique_id ||= "bl-icon-#{icon_name}-#{SecureRandom.hex(8)}"
|
21
38
|
end
|
22
39
|
|
23
40
|
##
|
@@ -25,7 +42,7 @@ module Blacklight
|
|
25
42
|
def options
|
26
43
|
{
|
27
44
|
class: classes,
|
28
|
-
"aria-hidden": (true if
|
45
|
+
"aria-hidden": (true if aria_hidden)
|
29
46
|
}
|
30
47
|
end
|
31
48
|
|
@@ -43,6 +60,10 @@ module Blacklight
|
|
43
60
|
file.source.force_encoding('UTF-8')
|
44
61
|
end
|
45
62
|
|
63
|
+
def ng_xml
|
64
|
+
@ng_xml ||= Nokogiri::XML(file_source).remove_namespaces!
|
65
|
+
end
|
66
|
+
|
46
67
|
private
|
47
68
|
|
48
69
|
def file
|
@@ -31,7 +31,9 @@ module Blacklight
|
|
31
31
|
#
|
32
32
|
# @return [Boolean]
|
33
33
|
def autofocus?
|
34
|
-
|
34
|
+
configuration.enable_search_bar_autofocus.present? &&
|
35
|
+
configuration.enable_search_bar_autofocus &&
|
36
|
+
controller.is_a?(Blacklight::Catalog) &&
|
35
37
|
controller.action_name == "index" &&
|
36
38
|
!controller.has_search_parameters?
|
37
39
|
end
|
@@ -4,35 +4,33 @@
|
|
4
4
|
# but it was simpler to leave them seperate instead of DRYing them, got confusing trying that.
|
5
5
|
# the data-doc-id attribute is used by our JS that converts to a checkbox/label.
|
6
6
|
-%>
|
7
|
-
<%
|
7
|
+
<% if bookmarked? document %>
|
8
8
|
<%= form_tag(bookmark_path(document),
|
9
|
-
method: :
|
10
|
-
class:
|
9
|
+
method: :delete,
|
10
|
+
class: "bookmark-toggle",
|
11
11
|
data: {
|
12
12
|
'doc-id' => document.id,
|
13
13
|
present: t('blacklight.search.bookmarks.present'),
|
14
14
|
absent: t('blacklight.search.bookmarks.absent'),
|
15
15
|
inprogress: t('blacklight.search.bookmarks.inprogress')
|
16
16
|
}) do %>
|
17
|
-
<%= submit_tag(t('blacklight.bookmarks.
|
17
|
+
<%= submit_tag(t('blacklight.bookmarks.remove.button'),
|
18
18
|
id: "bookmark_toggle_#{document.id.to_s.parameterize}",
|
19
|
-
class: "bookmark-
|
19
|
+
class: "bookmark-remove btn btn-outline-secondary") %>
|
20
20
|
<% end %>
|
21
21
|
<% else %>
|
22
22
|
<%= form_tag(bookmark_path(document),
|
23
|
-
method: :
|
24
|
-
class:
|
23
|
+
method: :put,
|
24
|
+
class: 'bookmark-toggle',
|
25
25
|
data: {
|
26
26
|
'doc-id' => document.id,
|
27
27
|
present: t('blacklight.search.bookmarks.present'),
|
28
28
|
absent: t('blacklight.search.bookmarks.absent'),
|
29
29
|
inprogress: t('blacklight.search.bookmarks.inprogress')
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
}) do %>
|
31
|
+
<%= submit_tag(t('blacklight.bookmarks.add.button'),
|
32
|
+
id: "bookmark_toggle_#{document.id.to_s.parameterize}",
|
33
|
+
class: "bookmark-add btn btn-outline-secondary") %>
|
34
34
|
<% end %>
|
35
35
|
<% end %>
|
36
|
-
<% else %>
|
37
|
-
|
38
36
|
<% end %>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<% # main container for facets/limits menu -%>
|
2
2
|
<% if has_facet_values? facet_field_names(groupname) %>
|
3
|
-
<div id="facets<%= "-#{groupname}" unless groupname.nil? %>" class="facets sidenav facets-toggleable-
|
3
|
+
<div id="facets<%= "-#{groupname}" unless groupname.nil? %>" class="facets sidenav facets-toggleable-md">
|
4
4
|
|
5
5
|
<div class="navbar">
|
6
6
|
<h2 class="facets-heading">
|