diff --git a/app/helpers/blacklight/blacklight_helper_behavior.rb b/app/helpers/blacklight/blacklight_helper_behavior.rb
index 2907e7e840..7f9c2fc459 100644
--- a/app/helpers/blacklight/blacklight_helper_behavior.rb
+++ b/app/helpers/blacklight/blacklight_helper_behavior.rb
@@ -5,25 +5,35 @@
#
module Blacklight::BlacklightHelperBehavior
include BlacklightUrlHelper
+ include BlacklightConfigurationHelper
include HashAsHiddenFieldsHelper
include RenderConstraintsHelper
include FacetsHelper
+ ##
+ # Get the name of this application, from either:
+ # - the Rails configuration
+ # - an i18n string (key: blacklight.application_name; preferred)
+ #
+ # @return [String] the application named
def application_name
return Rails.application.config.application_name if Rails.application.config.respond_to? :application_name
t('blacklight.application_name')
end
+ ##
# Create links from a documents dynamically
# provided export formats. Currently not used by standard BL layouts,
# but available for your custom layouts to provide link rel alternates.
#
# Returns empty string if no links available.
#
- # :unique => true, will ensure only one link is output for every
- # content type, as required eg in atom. Which one 'wins' is arbitrary.
- # :exclude => array of format shortnames, formats to not include at all.
+ # @params [SolrDocument] document
+ # @params [Hash] options
+ # @option options [Boolean] :unique ensures only one link is output for every
+ # content type, e.g. as required by atom
+ # @option options [Array] :exclude array of format shortnames to not include in the output
def render_link_rel_alternates(document=@document, options = {})
options = {:unique => false, :exclude => []}.merge(options)
@@ -44,28 +54,43 @@ def render_link_rel_alternates(document=@document, options = {})
return html.html_safe
end
+ ##
+ # Render OpenSearch headers for this search
+ # @return [String]
def render_opensearch_response_metadata
render :partial => 'catalog/opensearch_response_metadata'
end
+ ##
+ # Render classes for the element
+ # @return [String]
def render_body_class
extra_body_classes.join " "
end
- def render_search_bar
- render :partial=>'catalog/search_form'
- end
-
+ ##
+ # List of classes to be applied to the element
+ # @see render_body_class
+ # @return [Array]
def extra_body_classes
@extra_body_classes ||= ['blacklight-' + controller.controller_name, 'blacklight-' + [controller.controller_name, controller.action_name].join('-')]
end
- def render_document_list_partial options={}
- render :partial=>'catalog/document_list'
+ ##
+ # Render the search navbar
+ # @return [String]
+ def render_search_bar
+ render :partial=>'catalog/search_form'
end
- # Save function area for search results 'index' view, normally
- # renders next to title.
+ ##
+ # Render "docuemnt actions" area for search results view
+ # (normally renders next to title in the list view)
+ #
+ # @param [SolrDocument] document
+ # @param [Hash] options
+ # @option options [String] :wrapping_class
+ # @return [String]
def render_index_doc_actions(document, options={})
wrapping_class = options.delete(:wrapping_class) || "index-document-functions"
@@ -75,12 +100,18 @@ def render_index_doc_actions(document, options={})
content_tag("div", safe_join(content, "\n"), :class=> wrapping_class)
end
- # Save function area for item detail 'show' view, normally
- # renders next to title. By default includes 'Bookmarks'
+ ##
+ # Render "docuemnt actions" for the item detail 'show' view.
+ # (this normally renders next to title)
+ #
+ # By default includes 'Bookmarks'
+ #
+ # @param [SolrDocument] document
+ # @param [Hash] options
+ # @option options [String] :wrapping_class
+ # @return [String]
def render_show_doc_actions(document=@document, options={})
- # I'm not sure why this key is documentFunctions and #render_index_doc_actions uses wrapping_class.
- # TODO: remove documentFunctions key in Blacklight 5.x
- wrapping_class = options.delete(:documentFunctions) || options.delete(:wrapping_class) || "documentFunctions"
+ wrapping_class = options.delete(:wrapping_class) || "documentFunctions"
content = []
content << render(:partial => 'catalog/bookmark_control', :locals => {:document=> document}.merge(options)) if render_bookmarks_control?
@@ -89,17 +120,34 @@ def render_show_doc_actions(document=@document, options={})
end
##
- # Index fields to display for a type of document
- def index_fields document=nil
- blacklight_config.index_fields
+ # Determine whether to render a given field in the index view.
+ #
+ # @param [SolrDocument] document
+ # @param [Blacklight::Solr::Configuration::SolrField] solr_field
+ # @return [Boolean]
+ def should_render_index_field? document, solr_field
+ document.has?(solr_field.field) ||
+ (document.has_highlight_field? solr_field.field if solr_field.highlight) ||
+ solr_field.accessor
end
- def should_render_index_field? document, solr_field
+ ##
+ # Determine whether to render a given field in the show view
+ #
+ # @param [SolrDocument] document
+ # @param [Blacklight::Solr::Configuration::SolrField] solr_field
+ # @return [Boolean]
+ def should_render_show_field? document, solr_field
document.has?(solr_field.field) ||
(document.has_highlight_field? solr_field.field if solr_field.highlight) ||
solr_field.accessor
end
+ ##
+ # Determine whether to display spellcheck suggestions
+ #
+ # @param [Blacklight::SolrResponse] response
+ # @return [Boolean]
def should_show_spellcheck_suggestions? response
response.total <= spell_check_max and response.spelling.words.size > 0
end
@@ -156,69 +204,9 @@ def render_index_field_value *args
field_config = index_fields(document)[field]
value = options[:value] || get_field_values(document, field, field_config, options)
-
render_field_value value, field_config
end
- # Used in the show view for displaying the main solr document heading
- def document_heading document=nil
- document ||= @document
- render_field_value document[blacklight_config.view_config(:show).title_field] || document.id
- end
-
- # Used in the show view for setting the main html document title
- def document_show_html_title document=nil
- document ||= @document
-
- if blacklight_config.view_config(:show).html_title_field
- render_field_value(document[blacklight_config.view_config(:show).html_title_field])
- else
- document_heading document
- end
- end
-
- ##
- # Render the document "heading" (title) in a content tag
- # @overload render_document_heading(tag)
- # @overload render_document_heading(document, options)
- # @params [SolrDocument] document
- # @params [Hash] options
- # @options options [Symbol] :tag
- def render_document_heading(*args)
- options = args.extract_options!
- if args.first.is_a? SolrDocument
- document = args.shift
- tag = options[:tag]
- else
- document = nil
- tag = args.first || options[:tag]
- end
-
- tag ||= :h4
-
- content_tag(tag, render_field_value(document_heading(document)), :itemprop => "name")
- end
-
- # Used in the document_list partial (search view) for building a select element
- def sort_fields
- blacklight_config.sort_fields.map { |key, x| [x.label, x.key] }
- end
-
- # Used in the document list partial (search view) for creating a link to the document show action
- def document_show_link_field document=nil
- blacklight_config.view_config(document_index_view_type).title_field.to_sym
- end
-
- # Used in the search form partial for building a select tag
- def search_fields
- search_field_options_for_select
- end
-
- # used in the catalog/_show/_default partial
- def document_show_fields document=nil
- blacklight_config.show_fields
- end
-
##
# Render the show field label for a document
#
@@ -265,7 +253,6 @@ def render_document_show_field_label *args
# @param [Hash] opts
# @options opts [String] :value
def render_document_show_field_value *args
-
options = args.extract_options!
document = args.shift || options[:document]
@@ -276,6 +263,56 @@ def render_document_show_field_value *args
render_field_value value, field_config
end
+ ##
+ # Get the value of the document's "title" field, or a placeholder
+ # value (if empty)
+ #
+ # @param [SolrDocument] document
+ # @return [String]
+ def document_heading document=nil
+ document ||= @document
+ render_field_value(document[blacklight_config.view_config(:show).title_field] || document.id)
+ end
+
+ ##
+ # Get the document's "title" to display in the element.
+ # (by default, use the #document_heading)
+ #
+ # @see #document_heading
+ # @param [SolrDocument] document
+ # @return [String]
+ def document_show_html_title document=nil
+ document ||= @document
+
+ if blacklight_config.view_config(:show).html_title_field
+ render_field_value(document[blacklight_config.view_config(:show).html_title_field])
+ else
+ document_heading document
+ end
+ end
+
+ ##
+ # Render the document "heading" (title) in a content tag
+ # @overload render_document_heading(tag)
+ # @overload render_document_heading(document, options)
+ # @params [SolrDocument] document
+ # @params [Hash] options
+ # @options options [Symbol] :tag
+ def render_document_heading(*args)
+ options = args.extract_options!
+ if args.first.is_a? SolrDocument
+ document = args.shift
+ tag = options[:tag]
+ else
+ document = nil
+ tag = args.first || options[:tag]
+ end
+
+ tag ||= :h4
+
+ content_tag(tag, render_field_value(document_heading(document)), :itemprop => "name")
+ end
+
##
# Get the value for a document's field, and prepare to render it.
# - highlight_field
@@ -287,8 +324,12 @@ def render_document_show_field_value *args
# - link_to_search
# TODO : maybe this should be merged with render_field_value, and the ugly signature
# simplified by pushing some of this logic into the "model"
+ # @param [SolrDocument] document
+ # @param [String] field name
+ # @param [Blacklight::Solr::Configuration::SolrField] solr field configuration
+ # @param [Hash] options additional options to pass to the rendering helpers
def get_field_values document, field, field_config, options = {}
- # valuyes
+ # retrieving values
value = case
when (field_config and field_config.highlight)
# retrieve the document value from the highlighting response
@@ -311,7 +352,7 @@ def get_field_values document, field, field_config, options = {}
document.get(field, :sep => nil) if field
end
- # rendering
+ # rendering values
case
when (field_config and field_config.helper_method)
send(field_config.helper_method, options.merge(:document => document, :field => field, :value => value))
@@ -330,12 +371,12 @@ def get_field_values document, field, field_config, options = {}
end
end
- def should_render_show_field? document, solr_field
- document.has?(solr_field.field) ||
- (document.has_highlight_field? solr_field.field if solr_field.highlight) ||
- solr_field.accessor
- end
-
+ ##
+ # Render a value (or array of values) from a field
+ #
+ # @param [String] value or list of values to display
+ # @param [Blacklight::Solr::Configuration::SolrField] solr field configuration
+ # @return [String]
def render_field_value value=nil, field_config=nil
safe_values = Array(value).collect { |x| x.respond_to?(:force_encoding) ? x.force_encoding("UTF-8") : x }
@@ -346,10 +387,19 @@ def render_field_value value=nil, field_config=nil
safe_join(safe_values, (field_config.separator if field_config) || field_value_separator)
end
+ ##
+ # Default separator to use in #render_field_value
+ #
+ # @return [String]
def field_value_separator
', '
end
+ ##
+ # Get the current "view type" (and ensure it is a valid type)
+ #
+ # @param [Hash] the query parameters to check
+ # @return [Symbol]
def document_index_view_type query_params=params
if query_params[:view] and blacklight_config.view.keys.include? query_params[:view].to_sym
query_params[:view].to_sym
@@ -358,21 +408,42 @@ def document_index_view_type query_params=params
end
end
- def default_document_index_view_type
- blacklight_config.view.keys.first
- end
-
+ ##
+ # Render the document index view
+ #
+ # @param [Array] list of documents to render
+ # @param [Hash] locals to pass to the render call
+ # @return [String]
def render_document_index documents = nil, locals = {}
documents ||= @document_list
render_document_index_with_view(document_index_view_type, documents)
end
+ ##
+ # Render the document index for a grouped response
+ def render_grouped_document_index
+ render :partial => 'catalog/group_default'
+ end
+
+ ##
+ # Render the document index for the given view type with the
+ # list of documents.
+ #
+ # This method will interpolate the list of templates with
+ # the current view, and gracefully handles missing templates.
+ #
+ # @see #document_index_path_templates
+ #
+ # @param [String] view type
+ # @param [Array] list of documents to render
+ # @param [Hash] locals to pass to the render call
+ # @return [String]
def render_document_index_with_view view, documents, locals = {}
document_index_path_templates.each do |str|
# XXX rather than handling this logic through exceptions, maybe there's a Rails internals method
# for determining if a partial template exists..
begin
- return render(:partial => (str % { :index_view_type => view }), :locals => { :documents => documents })
+ return render(:partial => (str % { :index_view_type => view }), :locals => locals.merge(:documents => documents) )
rescue ActionView::MissingTemplate
nil
end
@@ -381,7 +452,11 @@ def render_document_index_with_view view, documents, locals = {}
return ""
end
- # a list of document partial templates to try to render for #render_document_index
+ ##
+ # A list of document partial templates to attempt to render
+ #
+ # @see #render_document_index_with_view
+ # @return [Array]
def document_index_path_templates
# first, the legacy template names for backwards compatbility
# followed by the new, inheritable style
@@ -389,37 +464,53 @@ def document_index_path_templates
@document_index_path_templates ||= ["document_%{index_view_type}", "catalog/document_%{index_view_type}", "catalog/document_list"]
end
- # Return a normalized partial name that can be used to contruct view partial path
+ ##
+ # Return a normalized partial name for rendering a single document
+ #
+ # @param [SolrDocument]
+ # @return [String]
def document_partial_name(document)
- # .to_s is necessary otherwise the default return value is not always a string
- # using "_" as sep. to more closely follow the views file naming conventions
- # parameterize uses "-" as the default sep. which throws errors
display_type = document[blacklight_config.view_config(:show).display_type_field]
return 'default' unless display_type
display_type = display_type.join(" ") if display_type.respond_to?(:join)
+ # .to_s is necessary otherwise the default return value is not always a string
+ # using "_" as sep. to more closely follow the views file naming conventions
+ # parameterize uses "-" as the default sep. which throws errors
"#{display_type.gsub("-"," ")}".parameterize("_").to_s
end
- def render_document_partials(doc, actions = [], locals ={})
- safe_join(actions.map do |action_name|
+ ##
+ # Return the list of partials for a given solr document
+ # @param [SolrDocument]
+ # @return [String]
+ def render_document_partials(doc, partials = [], locals ={})
+ safe_join(partials.map do |action_name|
render_document_partial(doc, action_name, locals)
end, "\n")
end
- # given a doc and action_name, this method attempts to render a partial template
- # based on the value of doc[:format]
- # if this value is blank (nil/empty) the "default" is used
- # if the partial is not found, the "default" partial is rendered instead
- def render_document_partial(doc, action_name, locals = {})
+ ##
+ # Given a doc and a base name for a partial, this method will attempt to render
+ # an appropriate partial based on the document format and view type.
+ #
+ # If a partial that matches the document format is not found,
+ # render a default partial for the base name.
+ #
+ # @see #document_partial_path_templates
+ #
+ # @param [SolrDocument] doc
+ # @param [String] base name for the partial
+ # @param [Hash] locales to pass through to the partials
+ def render_document_partial(doc, base_name, locals = {})
format = document_partial_name(doc)
document_partial_path_templates.each do |str|
# XXX rather than handling this logic through exceptions, maybe there's a Rails internals method
# for determining if a partial template exists..
begin
- return render :partial => (str % { :action_name => action_name, :format => format, :index_view_type => document_index_view_type }), :locals=>locals.merge({:document=>doc})
+ return render :partial => (str % { :action_name => base_name, :format => format, :index_view_type => document_index_view_type }), :locals=>locals.merge(:document=>doc)
rescue ActionView::MissingTemplate
nil
end
@@ -428,7 +519,15 @@ def render_document_partial(doc, action_name, locals = {})
return ''
end
- # a list of document partial templates to try to render for #render_document_partial
+ ##
+ # A list of document partial templates to try to render for a document
+ #
+ # The partial names will be interpolated with the following variables:
+ # - action_name: (e.g. index, show)
+ # - index_view_type: (the current view type, e.g. list, gallery)
+ # - format: the document's format (e.g. book)
+ #
+ # @see #render_document_partial
def document_partial_path_templates
# first, the legacy template names for backwards compatbility
# followed by the new, inheritable style
@@ -436,9 +535,15 @@ def document_partial_path_templates
@partial_path_templates ||= ["%{action_name}_%{index_view_type}_%{format}", "%{action_name}_%{index_view_type}_default", "%{action_name}_%{format}", "%{action_name}_default", "catalog/%{action_name}_%{format}", "catalog/_%{action_name}_partials/%{format}", "catalog/_%{action_name}_partials/default"]
end
-
-
- def render_document_index_label doc, opts
+ ##
+ # Render the document index heading
+ #
+ # @param [SolrDocument] doc
+ # @param [Hash] opts
+ # @option opts [Symbol] :label Render the given field from the document
+ # @option opts [Proc] :label Evaluate the given proc
+ # @option opts [String] :label Render the given string
+ def render_document_index_label doc, opts = {}
label = nil
label ||= doc.get(opts[:label], :sep => nil) if opts[:label].instance_of? Symbol
label ||= opts[:label].call(doc, opts) if opts[:label].instance_of? Proc
@@ -447,10 +552,15 @@ def render_document_index_label doc, opts
render_field_value label
end
- # Use case, you want to render an html partial from an XML (say, atom)
- # template. Rails API kind of lets us down, we need to hack Rails internals
- # a bit. code taken from:
+ ##
+ # Render a partial of an arbitrary format inside a
+ # template of a different format. (e.g. render an HTML
+ # partial from an XML template)
+ # code taken from:
# http://stackoverflow.com/questions/339130/how-do-i-render-a-partial-of-a-different-format-in-rails (zgchurch)
+ #
+ # @param [String] format suffix
+ # @yield
def with_format(format, &block)
old_formats = formats
self.formats = [format]
@@ -467,17 +577,9 @@ def render_grouped_response? response = @response
end
##
- # Render the grouped response
- def render_grouped_document_index grouped_key = nil
- render :partial => 'catalog/group_default'
- end
-
+ # Determine whether to render the bookmarks control
def render_bookmarks_control?
has_user_authentication_provider? and current_or_guest_user.present?
end
- def spell_check_max
- blacklight_config.spell_max
- end
-
end
diff --git a/app/helpers/blacklight/catalog_helper_behavior.rb b/app/helpers/blacklight/catalog_helper_behavior.rb
index 054b7d311a..ffdb06aab2 100644
--- a/app/helpers/blacklight/catalog_helper_behavior.rb
+++ b/app/helpers/blacklight/catalog_helper_behavior.rb
@@ -1,10 +1,13 @@
# -*- encoding : utf-8 -*-
module Blacklight::CatalogHelperBehavior
+ ##
# Override the Kaminari page_entries_info helper with our own, blacklight-aware
- # implementation
+ # implementation.
+ # Displays the "showing X through Y of N" message.
#
- # Pass in an RSolr::Response. Displays the "showing X through Y of N" message.
+ # @param [RSolr::Resource] (or other Kaminari-compatible objects)
+ # @return [String]
def page_entries_info(collection, options = {})
entry_name = if options[:entry_name]
options[:entry_name]
@@ -40,68 +43,122 @@ def page_entries_info(collection, options = {})
end
end
+ ##
+ # Get the offset counter for a document
+ #
+ # @param [Integer] document index
+ # @return [Integer]
def document_counter_with_offset idx
unless render_grouped_response?
idx + 1 + @response.params[:start].to_i
end
end
- # Like #page_entries_info above, but for an individual
- # item show page. Displays "showing X of Y items" message. Actually takes
- # data from session though (not a great design).
- # Code should call this method rather than interrogating session directly,
- # because implementation of where this data is stored/retrieved may change.
+ ##
+ # Like #page_entries_info above, but for an individual
+ # item show page. Displays "showing X of Y items" message.
+ #
+ # @see #page_entries_info
+ # @return [String]
def item_page_entry_info
t('blacklight.search.entry_pagination_info.other', :current => number_with_delimiter(search_session[:counter]), :total => number_with_delimiter(search_session[:total]), :count => search_session[:total].to_i).html_safe
end
+ ##
# Look up search field user-displayable label
# based on params[:qt] and blacklight_configuration.
def search_field_label(params)
h( label_for_search_field(params[:search_field]) )
end
+ ##
+ # Look up the current sort field, or provide the default if none is set
+ #
+ # @return [Blacklight::Configuration::SortField]
def current_sort_field
- blacklight_config.sort_fields[params[:sort]] || (blacklight_config.sort_fields.first ? blacklight_config.sort_fields.first.last : nil )
+ blacklight_config.sort_fields[params[:sort]] || default_sort_field
end
+ ##
+ # Look up the current per page value, or the default if none if set
+ #
+ # @return [Integer]
def current_per_page
- (@response.rows if @response and @response.rows > 0) || params.fetch(:per_page, (blacklight_config.per_page.first unless blacklight_config.per_page.blank?)).to_i
+ (@response.rows if @response and @response.rows > 0) || params.fetch(:per_page, default_per_page).to_i
end
- # Export to Refworks URL, called in _show_tools
+ ##
+ # Export to Refworks URL
+ #
+ # @param [SolrDocument]
+ # @return [String]
def refworks_export_url(document = @document)
"http://www.refworks.com/express/expressimport.asp?vendor=#{CGI.escape(application_name)}&filter=MARC%20Format&encoding=65001&url=#{CGI.escape(polymorphic_path(document, :format => 'refworks_marc_txt', :only_path => false))}"
end
+ ##
+ # Get the classes to add to a document's div
+ #
+ # @return [String]
def render_document_class(document = @document)
'blacklight-' + document.get(blacklight_config.view_config(document_index_view_type_field).display_type_field).parameterize rescue nil
end
+ ##
+ # Render the sidebar partial for a document
+ #
+ # @param [SolrDocument]
+ # @return [String]
def render_document_sidebar_partial(document = @document)
render :partial => 'show_sidebar'
end
+ ##
+ # Check if any search parameters have been set
+ # @return [Boolean]
def has_search_parameters?
!params[:q].blank? or !params[:f].blank? or !params[:search_field].blank?
end
+ ##
+ # Should we display the sort and per page widget?
+ #
+ # @param [Blacklight::SolrResponse]
+ # @return [Boolean]
def show_sort_and_per_page? response = nil
response ||= @response
!response.empty?
end
+ ##
+ # If no search parameters have been given, we should
+ # auto-focus the user's cursor into the searchbox
+ #
+ # @return [Boolean]
def should_autofocus_on_search_box?
controller.is_a? Blacklight::Catalog and
action_name == "index" and
!has_search_parameters?
end
+ ##
+ # Does the document have a thumbnail to render?
+ #
+ # @param [SolrDocument]
+ # @return [Boolean]
def has_thumbnail? document
blacklight_config.view_config(document_index_view_type).thumbnail_method or
blacklight_config.view_config(document_index_view_type).thumbnail_field && document.has?(blacklight_config.view_config(document_index_view_type).thumbnail_field)
end
+ ##
+ # Render the thumbnail, if available, for a document and
+ # link it to the document record.
+ #
+ # @param [SolrDocument]
+ # @param [Hash] options to pass to the image tag
+ # @param [Hash] url options to pass to #link_to_document
+ # @return [String]
def render_thumbnail_tag document, image_options = {}, url_options = {}
value = if blacklight_config.view_config(document_index_view_type).thumbnail_method
send(blacklight_config.view_config(document_index_view_type).thumbnail_method, document, image_options)
@@ -114,24 +171,40 @@ def render_thumbnail_tag document, image_options = {}, url_options = {}
end
end
+ ##
+ # Get the URL to a document's thumbnail image
+ #
+ # @param [SolrDocument]
+ # @return [String]
def thumbnail_url document
if document.has? blacklight_config.view_config(document_index_view_type).thumbnail_field
document.first(blacklight_config.view_config(document_index_view_type).thumbnail_field)
end
end
+ ##
+ # Get url parameters to a search within a grouped result set
+ #
+ # @param [Blacklight::SolrResponse::Group]
+ # @return [Hash]
def add_group_facet_params_and_redirect group
add_facet_params_and_redirect(group.field, group.key)
end
- def has_alternative_views?
- blacklight_config.view.keys.length > 1
- end
-
+ ##
+ # Render the view type icon for the results view picker
+ #
+ # @param [String]
+ # @return [String]
def render_view_type_group_icon view
content_tag :span, '', class: "glyphicon #{blacklight_config.view[view].icon_class || default_view_type_group_icon_classes(view) }"
end
+ ##
+ # Get the default view type classes for a view in the results view picker
+ #
+ # @param [String]
+ # @return [String]
def default_view_type_group_icon_classes view
"glyphicon-#{view.to_s.parameterize } view-icon-#{view.to_s.parameterize}"
end
diff --git a/app/helpers/blacklight/configuration_helper_behavior.rb b/app/helpers/blacklight/configuration_helper_behavior.rb
new file mode 100644
index 0000000000..ea8f0c6916
--- /dev/null
+++ b/app/helpers/blacklight/configuration_helper_behavior.rb
@@ -0,0 +1,61 @@
+module Blacklight::ConfigurationHelperBehavior
+
+ ##
+ # Index fields to display for a type of document
+ #
+ # @param [SolrDocument] document
+ # @return [Array]
+ def index_fields document=nil
+ blacklight_config.index_fields
+ end
+
+ # Used in the document_list partial (search view) for building a select element
+ def sort_fields
+ blacklight_config.sort_fields.map { |key, x| [x.label, x.key] }
+ end
+
+ # Used in the search form partial for building a select tag
+ def search_fields
+ search_field_options_for_select
+ end
+
+ # used in the catalog/_show/_default partial
+ def document_show_fields document=nil
+ blacklight_config.show_fields
+ end
+
+ ##
+ # Get the default index view type
+ def default_document_index_view_type
+ blacklight_config.view.keys.first
+ end
+
+ ##
+ # Check if there are alternative views configuration
+ def has_alternative_views?
+ blacklight_config.view.keys.length > 1
+ end
+
+ ##
+ # Maximum number of results for spell checking
+ def spell_check_max
+ blacklight_config.spell_max
+ end
+
+ # Used in the document list partial (search view) for creating a link to the document show action
+ def document_show_link_field document=nil
+ blacklight_config.view_config(document_index_view_type).title_field.to_sym
+ end
+
+ ##
+ # Default sort field
+ def default_sort_field
+ blacklight_config.sort_fields.first.last if blacklight_config.sort_fields.first
+ end
+
+ ##
+ # The default value for search results per page
+ def default_per_page
+ blacklight_config.per_page.first unless blacklight_config.per_page.blank?
+ end
+end
\ No newline at end of file
diff --git a/app/helpers/blacklight/facets_helper_behavior.rb b/app/helpers/blacklight/facets_helper_behavior.rb
index 8601e9273d..fd7f88cabe 100644
--- a/app/helpers/blacklight/facets_helper_behavior.rb
+++ b/app/helpers/blacklight/facets_helper_behavior.rb
@@ -2,11 +2,23 @@ module Blacklight::FacetsHelperBehavior
include Blacklight::Facet
+ ##
+ # Check if any of the given fields have values
+ #
+ # @param [Array]
+ # @param [Hash] options
+ # @return [Boolean]
def has_facet_values? fields = facet_field_names, options = {}
facets_from_request(fields).any? { |display_facet| !display_facet.items.empty? }
end
- # Render a collection of facet fields
+ ##
+ # Render a collection of facet fields.
+ # @see #render_facet_limit
+ #
+ # @param [Array]
+ # @param [Hash] options
+ # @return String
def render_facet_partials fields = facet_field_names, options = {}
safe_join(facets_from_request(fields).map do |display_facet|
render_facet_limit(display_facet, options)
@@ -14,14 +26,17 @@ def render_facet_partials fields = facet_field_names, options = {}
end
- # used in the catalog/_facets partial and elsewhere
+ ##
# Renders a single section for facet limit with a specified
# solr field used for faceting. Can be over-ridden for custom
# display on a per-facet basis.
#
# @param [Blacklight::SolrResponse::Facets::FacetField] display_facet
# @param [Hash] options parameters to use for rendering the facet limit partial
- #
+ # @option options [String] :partial partial to render
+ # @option options [String] :layout partial layout to render
+ # @option options [Hash] :locals locals to pass to the partial
+ # @return [String]
def render_facet_limit(display_facet, options = {})
return if not should_render_facet?(display_facet)
options = options.dup
@@ -39,7 +54,9 @@ def render_facet_limit(display_facet, options = {})
# Determine if Blacklight should render the display_facet or not
#
# By default, only render facets with items.
- # @param [Blacklight::SolrResponse::Facets::FacetField] display_facet
+ #
+ # @param [Blacklight::SolrResponse::Facets::FacetField] display_facet
+ # @return [Boolean]
def should_render_facet? display_facet
# display when show is nil or true
facet_config = facet_configuration_for_field(display_facet.name)
@@ -63,15 +80,21 @@ def should_render_facet? display_facet
end
##
- # if the facet is 'active', don't collapse
- # if the facet is configured to collapse (the default), collapse
- # if the facet is configured not to collapse, don't collapse
+ # Determine whether a facet should be rendered as collapsed or not.
+ # - if the facet is 'active', don't collapse
+ # - if the facet is configured to collapse (the default), collapse
+ # - if the facet is configured not to collapse, don't collapse
+ #
+ # @param [Blacklight::Configuration::FacetField]
+ # @return [Boolean]
def should_collapse_facet? facet_field
!facet_field_in_params?(facet_field.field) && facet_field.collapse
end
- # the name of the partial to use to render a facet field. Can be over-ridden for custom
- # display on a per-facet basis.
+ ##
+ # the name of the partial to use to render a facet field.
+ #
+ # @return [String]
def facet_partial_name(display_facet = nil)
config = facet_configuration_for_field(display_facet.name)
name = config.try(:partial)
@@ -79,17 +102,17 @@ def facet_partial_name(display_facet = nil)
name ||= "facet_limit"
end
- #
- # facet param helpers ->
- #
-
+ ##
# Standard display of a facet value in a list. Used in both _facets sidebar
# partial and catalog/facet expanded list. Will output facet value name as
- # a link to add that to your restrictions, with count in parens.
- # first arg item is a facet value item from rsolr-ext.
- # options consist of:
- # :suppress_link => true # do not make it a link
- # :route_set => my_engine # call link_to on engine routes.
+ # a link to add that to your restrictions, with count in parens.
+ #
+ # @param [Blacklight::SolrResponse::Facets::FacetField]
+ # @param [String] facet item
+ # @param [Hash] options
+ # @option options [Boolean] :suppress_link display the facet, but don't link to it
+ # @option options [Rails::Engine] :route_set route set to use to render the link
+ # @return [String]
def render_facet_value(facet_solr_field, item, options ={})
scope = options.delete(:route_set) || self
path = scope.url_for(add_facet_params_and_redirect(facet_solr_field, item).merge(only_path: true))
@@ -98,8 +121,9 @@ def render_facet_value(facet_solr_field, item, options ={})
end + render_facet_count(item.hits)
end
- # Standard display of a SELECTED facet value, no link, special span
- # with class, and 'remove' button.
+ ##
+ # Standard display of a SELECTED facet value (e.g. without a link and with a remove button)
+ # @params (see #render_facet_value)
def render_selected_facet_value(facet_solr_field, item)
content_tag(:span, :class => "facet-label") do
content_tag(:span, facet_display_value(facet_solr_field, item), :class => "selected") +
@@ -108,20 +132,35 @@ def render_selected_facet_value(facet_solr_field, item)
end + render_facet_count(item.hits, :classes => ["selected"])
end
+ ##
# Renders a count value for facet limits. Can be over-ridden locally
# to change style. And can be called by plugins to get consistent display.
#
- # option :class takes an array of classes to add to count span.
+ # @param [Integer] number of facet results
+ # @param [Hash] options
+ # @option options [Array] an array of classes to add to count span.
+ # @return [String]
def render_facet_count(num, options = {})
classes = (options[:classes] || []) << "facet-count"
content_tag("span", t('blacklight.search.facets.count', :number => num), :class => classes)
end
+ ##
+ # Are any facet restrictions for a field in the query parameters?
+ #
+ # @param [String] facet field
+ # @return [Boolean]
def facet_field_in_params? field
params[:f] and params[:f][field]
end
- # true or false, depending on whether the field and value is in params[:f]
+ ##
+ # Check if the query parameters have the given facet field with the
+ # given value.
+ #
+ # @param [Object] facet field
+ # @param [Object] facet value
+ # @return [Boolean]
def facet_in_params?(field, item)
if item and item.respond_to? :field
field = item.field
@@ -132,6 +171,12 @@ def facet_in_params?(field, item)
facet_field_in_params?(field) and params[:f][field].include?(value)
end
+ ##
+ # Get the displayable version of a facet's value
+ #
+ # @param [Object] field
+ # @param [String] item value
+ # @return [String]
def facet_display_value field, item
facet_config = facet_configuration_for_field(field)
diff --git a/app/helpers/blacklight/hash_as_hidden_fields_helper_behavior.rb b/app/helpers/blacklight/hash_as_hidden_fields_helper_behavior.rb
index 9c73fb2f41..83419efda3 100644
--- a/app/helpers/blacklight/hash_as_hidden_fields_helper_behavior.rb
+++ b/app/helpers/blacklight/hash_as_hidden_fields_helper_behavior.rb
@@ -11,9 +11,12 @@
# to form fields used for sort and change per-page
module Blacklight::HashAsHiddenFieldsHelperBehavior
+ ##
# Writes out zero or more elements, completely
# representing a hash passed in using Rails-style request parameters
- # for hashes nested with arrays and other hashes.
+ # for hashes nested with arrays and other hashes.
+ # @param [Hash]
+ # @return [String]
def render_hash_as_hidden_fields(hash)
hidden_fields = []
diff --git a/app/helpers/blacklight/render_constraints_helper_behavior.rb b/app/helpers/blacklight/render_constraints_helper_behavior.rb
index 326836ebdc..470174efc7 100644
--- a/app/helpers/blacklight/render_constraints_helper_behavior.rb
+++ b/app/helpers/blacklight/render_constraints_helper_behavior.rb
@@ -7,16 +7,30 @@
# search results page (render_constraints(_*))
module Blacklight::RenderConstraintsHelperBehavior
+ ##
+ # Check if the query has any constraints defined (a query, facet, etc)
+ #
+ # @param [Hash] query parameters
+ # @return [Boolean]
def query_has_constraints?(localized_params = params)
!(localized_params[:q].blank? and localized_params[:f].blank?)
end
- # Render actual constraints, not including header or footer
+ ##
+ # Render the actual constraints, not including header or footer
# info.
+ #
+ # @param [Hash] query parameters
+ # @return [String]
def render_constraints(localized_params = params)
render_constraints_query(localized_params) + render_constraints_filters(localized_params)
end
+ ##
+ # Render the query constraints
+ #
+ # @param [Hash] query parameters
+ # @return [String]
def render_constraints_query(localized_params = params)
# So simple don't need a view template, we can just do it here.
if (!localized_params[:q].blank?)
@@ -36,6 +50,11 @@ def render_constraints_query(localized_params = params)
end
end
+ ##
+ # Render the facet constraints
+ #
+ # @param [Hash] query parameters
+ # @return [String]
def render_constraints_filters(localized_params = params)
return "".html_safe unless localized_params[:f]
content = []
@@ -46,6 +65,13 @@ def render_constraints_filters(localized_params = params)
safe_join(content.flatten, "\n")
end
+ ##
+ # Render a single facet's constraint
+ #
+ # @param [String] facet field
+ # @param [Array] selected facet values
+ # @param [Hash] query parameters
+ # @return [String]
def render_filter_element(facet, values, localized_params)
facet_config = facet_configuration_for_field(facet)
@@ -66,15 +92,12 @@ def render_filter_element(facet, values, localized_params)
#
# Can pass in nil label if desired.
#
- # options:
- # [:remove]
- # url to execute for a 'remove' action
- # [:classes]
- # can be an array of classes to add to container span for constraint.
- # [:escape_label]
- # default true, HTML escape.
- # [:escape_value]
- # default true, HTML escape.
+ # @param [String] label to display
+ # @param [String] value to display
+ # @param [Hash] options
+ # @option options [String] :remove url to execute for a 'remove' action
+ # @option options [Array] :classes an array of classes to add to container span for constraint.
+ # @return [String]
def render_constraint_element(label, value, options = {})
render(:partial => "catalog/constraints_element", :locals => {:label => label, :value => value, :options => options})
end
diff --git a/app/helpers/blacklight/search_history_constraints_helper_behavior.rb b/app/helpers/blacklight/search_history_constraints_helper_behavior.rb
index 2d8fa9c989..ab7a9a502e 100644
--- a/app/helpers/blacklight/search_history_constraints_helper_behavior.rb
+++ b/app/helpers/blacklight/search_history_constraints_helper_behavior.rb
@@ -16,6 +16,8 @@ def render_search_to_s(params)
render_search_to_s_filters(params)
end
+ ##
+ # Render the search query constraint
def render_search_to_s_q(params)
return "".html_safe if params[:q].blank?
@@ -26,6 +28,8 @@ def render_search_to_s_q(params)
render_search_to_s_element(label , render_filter_value(params[:q]) )
end
+ ##
+ # Render the search facet constraints
def render_search_to_s_filters(params)
return "".html_safe unless params[:f]
@@ -45,11 +49,15 @@ def render_search_to_s_element(key, value, options = {})
content_tag(:span, render_filter_name(key) + content_tag(:span, value, :class => 'filterValues'), :class => 'constraint')
end
+ ##
+ # Render the name of the facet
def render_filter_name name
return "".html_safe if name.blank?
content_tag(:span, t('blacklight.search.filters.label', :label => name), :class => 'filterName')
end
+ ##
+ # Render the value of the facet
def render_filter_value value, key = nil
display_value = value
display_value = facet_display_value(key, value) if key
diff --git a/app/helpers/blacklight/url_helper_behavior.rb b/app/helpers/blacklight/url_helper_behavior.rb
index 7d6b5eb6f2..49ff5f71f0 100644
--- a/app/helpers/blacklight/url_helper_behavior.rb
+++ b/app/helpers/blacklight/url_helper_behavior.rb
@@ -10,18 +10,24 @@ def link_to_document(doc, opts={:label=>nil, :counter => nil})
link_to label, doc, search_session_params(opts[:counter]).merge(opts.reject { |k,v| [:label, :counter].include? k })
end
+ ##
+ # Link to the previous document in the current search context
def link_to_previous_document(previous_document)
link_to_unless previous_document.nil?, raw(t('views.pagination.previous')), previous_document, search_session_params(search_session[:counter].to_i - 1).merge(:class => "previous", :rel => 'prev') do
content_tag :span, raw(t('views.pagination.previous')), :class => 'previous'
end
end
+ ##
+ # Link to the next document in the current search context
def link_to_next_document(next_document)
link_to_unless next_document.nil?, raw(t('views.pagination.next')), next_document, search_session_params(search_session[:counter].to_i + 1).merge(:class => "next", :rel => 'next') do
content_tag :span, raw(t('views.pagination.next')), :class => 'next'
end
end
+ ##
+ # Current search context parameters
def search_session_params counter
{ :'data-counter' => counter, :'data-search_id' => current_search_session.try(:id) }
end
@@ -175,6 +181,7 @@ def add_facet_params_and_redirect(field, item)
new_params[:action] = "index"
new_params
end
+
# copies the current params (or whatever is passed in as the 3rd arg)
# removes the field value from params[:f]
# removes the field if there are no more values in params[:f][field]
diff --git a/app/helpers/blacklight_configuration_helper.rb b/app/helpers/blacklight_configuration_helper.rb
new file mode 100644
index 0000000000..e75427a54d
--- /dev/null
+++ b/app/helpers/blacklight_configuration_helper.rb
@@ -0,0 +1,3 @@
+module BlacklightConfigurationHelper
+ include Blacklight::ConfigurationHelperBehavior
+end
\ No newline at end of file
diff --git a/app/views/catalog/_constraints_element.html.erb b/app/views/catalog/_constraints_element.html.erb
index 8a33b1700c..5ac5dae624 100644
--- a/app/views/catalog/_constraints_element.html.erb
+++ b/app/views/catalog/_constraints_element.html.erb
@@ -5,26 +5,24 @@
# :remove => url for a remove constraint link
# :classes => array of classes to add to container span
options ||= {}
- options[:escape_label] = true unless options.has_key?(:escape_label)
- options[:escape_value] = true unless options.has_key?(:escape_value)
-%>
">
<%- unless label.blank? -%>
- <%= options[:escape_label] ? h(label) : raw(label) %>
+ <%= label %>
<%- end -%>
<%- unless value.blank? -%>
- <%= options[:escape_value] ? h(value) : raw(value) %>
+ <%= value %>
<%- end -%>
<%- unless options[:remove].blank? -%>
<% accessible_remove_label = content_tag :span, :class => 'sr-only' do
if label.blank?
- t('blacklight.search.filters.remove.value', :value => (options[:escape_value] ? h(value) : value))
+ t('blacklight.search.filters.remove.value', :value => value)
else
- t('blacklight.search.filters.remove.label_value', :label => (options[:escape_label] ? h(label) : label), :value => (options[:escape_value] ? h(value) : value))
+ t('blacklight.search.filters.remove.label_value', :label => label, :value => value)
end
end
%>
diff --git a/lib/blacklight/solr/document.rb b/lib/blacklight/solr/document.rb
index b4b96aa6e5..545d03e104 100644
--- a/lib/blacklight/solr/document.rb
+++ b/lib/blacklight/solr/document.rb
@@ -114,7 +114,7 @@ def id
end
def to_param
- id
+ id.to_s
end
def as_json(options = nil)
diff --git a/lib/blacklight/utils.rb b/lib/blacklight/utils.rb
index 967913288d..3cb8ae1314 100644
--- a/lib/blacklight/utils.rb
+++ b/lib/blacklight/utils.rb
@@ -1,7 +1,7 @@
require 'ostruct'
module Blacklight
class OpenStructWithHashAccess < OpenStruct
- delegate :keys, :has_key?, :delete, :length, :reject!, :select!, :include, :fetch, :to => :to_h
+ delegate :keys, :each, :map, :has_key?, :delete, :length, :reject!, :select!, :include, :fetch, :to => :to_h
def []=(key, value)
send "#{key}=", value
diff --git a/lib/generators/blacklight/install_generator.rb b/lib/generators/blacklight/install_generator.rb
index cec3cc3fb0..a53cb2e19e 100644
--- a/lib/generators/blacklight/install_generator.rb
+++ b/lib/generators/blacklight/install_generator.rb
@@ -88,5 +88,9 @@ def add_sass_configuration
EOF
end
end
+
+ def inject_blacklight_i18n_strings
+ copy_file "blacklight.en.yml", "config/locales/blacklight.en.yml"
+ end
end
end
\ No newline at end of file
diff --git a/lib/generators/blacklight/templates/blacklight.en.yml b/lib/generators/blacklight/templates/blacklight.en.yml
new file mode 100644
index 0000000000..ff834b2f07
--- /dev/null
+++ b/lib/generators/blacklight/templates/blacklight.en.yml
@@ -0,0 +1,3 @@
+en:
+ blacklight:
+ application_name: 'Blacklight'
\ No newline at end of file
diff --git a/spec/helpers/configuration_helper_spec.rb b/spec/helpers/configuration_helper_spec.rb
new file mode 100644
index 0000000000..86f4f33f0f
--- /dev/null
+++ b/spec/helpers/configuration_helper_spec.rb
@@ -0,0 +1,61 @@
+require 'spec_helper'
+
+describe BlacklightConfigurationHelper do
+ let(:blacklight_config) { Blacklight::Configuration.new }
+ let(:config_value) { double() }
+
+ before :each do
+ helper.stub(blacklight_config: blacklight_config)
+ end
+
+ describe "#index_fields" do
+ it "should pass through the configuration" do
+ blacklight_config.stub(index_fields: config_value)
+ expect(helper.index_fields).to eq config_value
+ end
+ end
+
+ describe "#sort_fields" do
+ it "should convert the sort fields to select-ready values" do
+ blacklight_config.stub(sort_fields: { 'a' => double(key: 'a', label: 'a'), 'b' => double(key: 'b', label: 'b'), })
+ expect(helper.sort_fields).to eq [['a', 'a'], ['b', 'b']]
+ end
+ end
+
+ describe "#document_show_fields" do
+ it "should pass through the configuration" do
+ blacklight_config.stub(show_fields: config_value)
+ expect(helper.document_show_fields).to eq config_value
+ end
+ end
+
+ describe "#default_document_index_view_type" do
+ it "should be the first configured index view" do
+ blacklight_config.stub(view: { 'a' => true, 'b' => true})
+ expect(helper.default_document_index_view_type).to eq 'a'
+ end
+ end
+
+ describe "#has_alternative_views?" do
+ subject { helper.has_alternative_views?}
+ describe "with a single view defined" do
+ it { should be_false }
+ end
+
+ describe "with multiple views defined" do
+ before do
+ blacklight_config.view.abc
+ blacklight_config.view.xyz
+ end
+
+ it { should be_true }
+ end
+ end
+
+ describe "#spell_check_max" do
+ it "should pass through the configuration" do
+ blacklight_config.stub(spell_max: config_value)
+ expect(helper.spell_check_max).to eq config_value
+ end
+ end
+end
\ No newline at end of file
diff --git a/spec/helpers/url_helper_spec.rb b/spec/helpers/url_helper_spec.rb
index 7c968bb6d0..10b5640910 100644
--- a/spec/helpers/url_helper_spec.rb
+++ b/spec/helpers/url_helper_spec.rb
@@ -225,6 +225,13 @@ def params
@document = SolrDocument.new('id'=>'123456')
expect(link_to_document(@document,:label=>"Some crazy long label...")).to_not match(/title=/)
end
+
+ it "should work with integer ids" do
+ data = {'id'=> 123456 }
+ @document = SolrDocument.new(data)
+ expect(link_to_document(@document)).to have_selector("a")
+ end
+
end
describe "link_to_previous_search" do
diff --git a/spec/lib/blacklight/solr/document_spec.rb b/spec/lib/blacklight/solr/document_spec.rb
index da0dfee1dd..03de296aa2 100644
--- a/spec/lib/blacklight/solr/document_spec.rb
+++ b/spec/lib/blacklight/solr/document_spec.rb
@@ -44,6 +44,14 @@ def my_extension_method
@document = MockDocument.new :id => 'asdf', :my_unique_key => '1234'
expect(@document.id).to eq '1234'
end
+
+ end
+
+ describe "#to_param" do
+ it "should be a string" do
+ @document = MockDocument.new :id => 1234
+ expect(@document.to_param).to eq '1234'
+ end
end
context "Extendability" do
diff --git a/spec/views/catalog/_constraints_element.html.erb_spec.rb b/spec/views/catalog/_constraints_element.html.erb_spec.rb
index 099e93a80f..623795f4aa 100644
--- a/spec/views/catalog/_constraints_element.html.erb_spec.rb
+++ b/spec/views/catalog/_constraints_element.html.erb_spec.rb
@@ -52,7 +52,7 @@
describe "with no escaping" do
before do
- render( :partial => "catalog/constraints_element", :locals => {:label => "my label", :value => "my value", :options => {:escape_label => false, :escape_value => false}} )
+ render( :partial => "catalog/constraints_element", :locals => {:label => "my label".html_safe, :value => "my value".html_safe} )
end
it "should not escape key and value" do
expect(rendered).to have_selector("span.appliedFilter.constraint span.filterName span.custom_label")