Skip to content

Commit

Permalink
Add support for Blacklight hit-highlighting in the full-text field
Browse files Browse the repository at this point in the history
  • Loading branch information
jkeck committed Dec 20, 2017
1 parent 9940e35 commit 6ebd4cd
Show file tree
Hide file tree
Showing 9 changed files with 203 additions and 2 deletions.
2 changes: 1 addition & 1 deletion app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
//= require blacklight_gallery
//= require blacklight_heatmaps
//= require blacklight_oembed
//= require full_text_collapse
//= require index_status_typeahead
//= require nested_related_items
//= require openseadragon
Expand All @@ -37,4 +38,3 @@
// For blacklight_range_limit built-in JS, if you don't want it you don't need
// this:
//= require 'blacklight_range_limit'

23 changes: 23 additions & 0 deletions app/assets/javascripts/full_text_collapse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* global Blacklight */

Blacklight.onLoad(function(){
var uniqueId = (function() {
var uuid = 0;

return function(el) {
el.id = 'ui-id-' + ( ++uuid );
};
} )();

$('dd.blacklight-full_text_tesimv').addClass('collapse').each(function() {
$(this).attr('id', uniqueId(this));
});

$('dt.blacklight-full_text_tesimv').each(function() {
$(this).text($(this).text().replace(/:$/, ''));
$(this).attr('data-toggle', 'collapse');
$(this).attr('data-target', '#' + $(this).next('dd').attr('id'));
});

$('dd.blacklight-full_text_tesimv').collapse({ toggle: false });
});
1 change: 1 addition & 0 deletions app/assets/stylesheets/base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
@import "viewers";
@import "modules/view_metadata";
@import "modules/related_item";
@import "modules/full_text_highlight";
32 changes: 32 additions & 0 deletions app/assets/stylesheets/modules/full_text_highlight.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
dt.blacklight-full_text_tesimv {
@extend .h4;
cursor: pointer;
display: inline-block;
float: none;
text-align: initial;
width: auto;
// collapse carets shamelessly stolen from blacklight facets
&[data-toggle="collapse"]::after {
// symbol for "opening" panels
content: "\e114";
float: right;
font-family: "Glyphicons Halflings";
font-size: 0.8em;
line-height: normal;
padding-left: 2ch;
}

&.collapsed::after {
// symbol for "collapsed" panels
content: "\e080";
}
}

dd.blacklight-full_text_tesimv {
float: none;
margin-left: 0;

em {
font-weight: bold;
}
}
33 changes: 32 additions & 1 deletion app/controllers/catalog_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ class CatalogController < ApplicationController
## Default parameters to send to solr for all search-like requests. See also SolrHelper#solr_search_params
config.default_solr_params = {
qt: 'search',
fl: '*'
fl: '*',
hl: true,
'hl.fl' => 'full_text_tesimv',
'hl.snippets' => 5,
'hl.fragsize' => 240,
'hl.mergeContiguous' => true,
'hl.useFastVectorHighlighter' => true
}

config.default_autocomplete_solr_params = {
Expand Down Expand Up @@ -208,6 +214,18 @@ class CatalogController < ApplicationController
config.add_index_field 'manuscript_number_tesim', label: 'Manuscript number'
config.add_index_field 'range_labels_tesim', label: 'Section'
config.add_index_field 'related_document_id_ssim', label: 'Manuscript', helper_method: :manuscript_link
config.add_index_field(
'full_text_tesimv',
if: lambda do |*args|
# bail out to true (show the field) if we don't have 3 arguments (context being the added argument)
# This is required for the metadata configuration admin page to return the field properly.
return true if args.length < 3
full_text_highlight_exists_in_response?(*args)
end,
label: 'Preview matches in document text',
highlight: true,
helper_method: :render_fulltext_highlight
)
# "fielded" search configuration. Used by pulldown among other places.
# For supported keys in hash, see rdoc for Blacklight::SearchFields
#
Expand Down Expand Up @@ -352,4 +370,17 @@ def metadata
def start_new_search_session?
super && params[:format] != 'json'
end

class << self
# Blacklight's highlighting feature assumes that the metadata exists in the page
# and replaces the rendered version from the dopcument with that of the highlighting
# section. In the case of our full text field, we do not render it in the normal results
# so we need to not display the field at all unless it was returned in the highlighting.
def full_text_highlight_exists_in_response?(context, config, document)
response = context.instance_variable_get(:@response)
document_highlight = response.dig('highlighting', document['id'])
return true if document_highlight.present? && document_highlight[config.key].present?
false
end
end
end
9 changes: 9 additions & 0 deletions app/helpers/catalog_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,15 @@ def manuscript_link(options = {})
link_to link_title, spotlight.exhibit_solr_document_path(current_exhibit, druid)
end

def render_fulltext_highlight(args)
return if args[:value].blank?
safe_join(args[:value].map do |val|
content_tag('p') do
val
end
end, '')
end

private

def thumbnail_tag_image_path(document)
Expand Down
34 changes: 34 additions & 0 deletions spec/features/full_text_highlight_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.feature 'Full text highlighting' do
let(:exhibit) { create(:exhibit) }
let(:dor_harvester) { DorHarvester.new(druid_list: druid, exhibit: exhibit) }

before do
allow(Spotlight::Engine.config).to receive(:filter_resources_by_exhibit).and_return(false)
end

context 'when a document has a full text highlight hit' do
it 'shows the full-text hightlight field and provides a toggle', js: true do
visit spotlight.search_exhibit_catalog_path(exhibit, q: 'structure')

expect(page).to have_css('dt', text: 'Preview matches in document text')

expect(page).not_to have_css('dd p', text: 'about need for data structures capable of storing', visible: true)
page.find('dt', text: 'Preview matches in document text').click
expect(page).to have_css('dd p', text: 'about need for data structures capable of storing', visible: true)
end
end

context 'when a document does not have a full text highlight hit' do
it 'does not include full-text highlight', js: true do
visit spotlight.search_exhibit_catalog_path(exhibit, q: 'Maps')

expect(page).to have_css('.documents-list .document') # there are results

expect(page).not_to have_css('dt', text: 'Preview matches in document text')
end
end
end
56 changes: 56 additions & 0 deletions spec/fixtures/sample_solr_docs.json

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions spec/helpers/catalog_helper_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,19 @@ def current_exhibit
end
end
end

describe '#render_fulltext_highlight' do
context 'when there is no value' do
it 'is nil' do
expect(helper.render_fulltext_highlight(value: [])).to be_nil
end
end

context 'when there are values' do
it 'wraps each value in a paragraph tag' do
ps = helper.render_fulltext_highlight(value: %w(Value1 Value2))
expect(ps).to eq '<p>Value1</p><p>Value2</p>'
end
end
end
end

0 comments on commit 6ebd4cd

Please sign in to comment.