blacklight_advanced_search 1.0.0pre1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/LICENSE +14 -0
- data/README.rdoc +172 -0
- data/Rakefile +6 -0
- data/VERSION +1 -0
- data/app/controllers/advanced_controller.rb +61 -0
- data/app/controllers/application_controller.rb +5 -0
- data/app/helpers/advanced_helper.rb +40 -0
- data/app/views/advanced/_advanced_search_facets.html.erb +16 -0
- data/app/views/advanced/_advanced_search_fields.html.erb +6 -0
- data/app/views/advanced/_advanced_search_form.html.erb +48 -0
- data/app/views/advanced/_advanced_search_help.html.erb +22 -0
- data/app/views/advanced/index.html.erb +10 -0
- data/app/views/blacklight_advanced_search/_facet_limit.html.erb +25 -0
- data/blacklight_advanced_search.gemspec +24 -0
- data/config/routes.rb +3 -0
- data/install.rb +0 -0
- data/lib/blacklight_advanced_search/advanced_query_parser.rb +61 -0
- data/lib/blacklight_advanced_search/catalog_helper_override.rb +53 -0
- data/lib/blacklight_advanced_search/controller.rb +101 -0
- data/lib/blacklight_advanced_search/engine.rb +47 -0
- data/lib/blacklight_advanced_search/filter_parser.rb +13 -0
- data/lib/blacklight_advanced_search/parsing_nesting_parser.rb +18 -0
- data/lib/blacklight_advanced_search/render_constraints_override.rb +96 -0
- data/lib/blacklight_advanced_search/version.rb +10 -0
- data/lib/blacklight_advanced_search.rb +74 -0
- data/lib/generators/blacklight_advanced_search/assets_generator.rb +25 -0
- data/lib/generators/blacklight_advanced_search/blacklight_advanced_search_generator.rb +11 -0
- data/lib/generators/blacklight_advanced_search/templates/_search_form.html.erb +13 -0
- data/lib/generators/blacklight_advanced_search/templates/blacklight_advanced_search_config.rb +86 -0
- data/lib/generators/blacklight_advanced_search/templates/public/javascripts/blacklight_advanced_search_javascript.js +62 -0
- data/lib/generators/blacklight_advanced_search/templates/public/stylesheets/advanced_results.css +41 -0
- data/lib/generators/blacklight_advanced_search/templates/public/stylesheets/blacklight_advanced_search_styles.css +129 -0
- data/lib/parsing_nesting/Readme.rdoc +160 -0
- data/lib/parsing_nesting/grammar.rb +78 -0
- data/lib/parsing_nesting/tree.rb +457 -0
- data/spec/lib/filter_parser_spec.rb +28 -0
- data/spec/parsing_nesting/build_tree_spec.rb +238 -0
- data/spec/parsing_nesting/consuming_spec.rb +49 -0
- data/spec/parsing_nesting/to_solr_spec.rb +360 -0
- data/spec/rcov.opts +3 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/support/blacklight_mock.rb +5 -0
- data/uninstall.rb +1 -0
- metadata +164 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'blacklight_advanced_search/parsing_nesting_parser'
|
2
|
+
|
3
|
+
# This module gets included into CatalogController, or another SolrHelper
|
4
|
+
# includer, to add behavior into solr_search_params_logic.
|
5
|
+
module BlacklightAdvancedSearch::Controller
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
if BlacklightAdvancedSearch.config[:advanced_parse_q]
|
10
|
+
# Only to parse AND/OR in ordinary 'q'
|
11
|
+
solr_search_params_logic << :add_advanced_parse_q_to_solr
|
12
|
+
end
|
13
|
+
|
14
|
+
# Always, to parse adv search form params.
|
15
|
+
solr_search_params_logic << :add_advanced_search_to_solr
|
16
|
+
|
17
|
+
|
18
|
+
helper BlacklightAdvancedSearch::RenderConstraintsOverride
|
19
|
+
helper BlacklightAdvancedSearch::CatalogHelperOverride
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
# this method should get added into the solr_search_params_logic
|
24
|
+
# list, in a position AFTER normal query handling (:add_query_to_solr),
|
25
|
+
# so it'll overwrite that if and only if it's an advanced search.
|
26
|
+
# adds a 'q' and 'fq's based on advanced search form input.
|
27
|
+
def add_advanced_search_to_solr(solr_parameters, req_params = params)
|
28
|
+
# If we've got the hint that we're doing an 'advanced' search, then
|
29
|
+
# map that to solr #q, over-riding whatever some other logic may have set, yeah.
|
30
|
+
# the hint right now is :search_field request param is set to a magic
|
31
|
+
# key.
|
32
|
+
if (req_params[:search_field] == BlacklightAdvancedSearch.config[:url_key] ||
|
33
|
+
req_params[:f_inclusive])
|
34
|
+
# Set this as a controller instance variable, not sure if some views/helpers depend on it. Better to leave it as a local variable
|
35
|
+
# if not, more investigation later.
|
36
|
+
@advanced_query = BlacklightAdvancedSearch::QueryParser.new(req_params, BlacklightAdvancedSearch.config )
|
37
|
+
deep_merge!(solr_parameters, @advanced_query.to_solr )
|
38
|
+
if @advanced_query.keyword_queries.length > 0
|
39
|
+
# force :qt if set
|
40
|
+
solr_parameters[:qt] = BlacklightAdvancedSearch.config[:qt] if BlacklightAdvancedSearch.config[:qt]
|
41
|
+
solr_parameters[:defType] = "lucene"
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# This method can be included in solr_search_params_logic to have us
|
48
|
+
# parse an ordinary entered :q for AND/OR/NOT and produce appropriate
|
49
|
+
# Solr query. Note that it is NOT included in solr_search_params_logic
|
50
|
+
# by default when this module is included, because it is optional behavior.
|
51
|
+
# BlacklightAdvancedSearch init code will add it to CatalogController
|
52
|
+
# if it's configured to do so. You can of course add it yourself
|
53
|
+
# manually too.
|
54
|
+
def add_advanced_parse_q_to_solr(solr_parameters, req_params = params)
|
55
|
+
unless req_params[:q].blank?
|
56
|
+
field_def = Blacklight.search_field_def_for_key( req_params[:search_field]) ||
|
57
|
+
Blacklight.default_search_field
|
58
|
+
solr_direct_params = field_def[:solr_parameters] || {}
|
59
|
+
solr_local_params = field_def[:solr_local_parameters] || {}
|
60
|
+
|
61
|
+
deep_merge!(solr_parameters, solr_direct_params)
|
62
|
+
|
63
|
+
deep_merge!(
|
64
|
+
solr_parameters,
|
65
|
+
ParsingNesting::Tree.parse(req_params[:q]).to_single_query_params( solr_local_params )
|
66
|
+
)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
protected
|
72
|
+
# Merges new_hash into source_hash, without modifying arguments, but
|
73
|
+
# will merge nested arrays and hashes too. Also will NOT merge nil or blank
|
74
|
+
# from new_hash into old_hash
|
75
|
+
def deep_merge!(source_hash, new_hash)
|
76
|
+
source_hash.merge!(new_hash) do |key, old, new|
|
77
|
+
if new.respond_to?(:blank) && new.blank?
|
78
|
+
old
|
79
|
+
elsif (old.kind_of?(Hash) and new.kind_of?(Hash))
|
80
|
+
deep_merge!(old, new)
|
81
|
+
elsif (old.kind_of?(Array) and new.kind_of?(Array))
|
82
|
+
old.concat(new).uniq
|
83
|
+
elsif new.nil?
|
84
|
+
# Allowing nil values to over-write on merge messes things up.
|
85
|
+
# don't set a nil value if you really want to force blank, set
|
86
|
+
# empty string.
|
87
|
+
old
|
88
|
+
else
|
89
|
+
new
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'blacklight'
|
2
|
+
require 'blacklight_advanced_search'
|
3
|
+
require 'rails'
|
4
|
+
|
5
|
+
module BlacklightAdvancedSearch
|
6
|
+
class Engine < Rails::Engine
|
7
|
+
|
8
|
+
config.after_initialize do
|
9
|
+
# After local app initializers that may set some config, we
|
10
|
+
# finish it off with defaults and normalization.
|
11
|
+
BlacklightAdvancedSearch.init
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
# Do these things in a to_prepare block, to try and make them work
|
16
|
+
# in development mode with class-reloading. The trick is we can't
|
17
|
+
# be sure if the controllers we're modifying are being reloaded in
|
18
|
+
# dev mode, if they are in the BL plugin and haven't been copied to
|
19
|
+
# local, they won't be. But we do our best.
|
20
|
+
config.to_prepare do
|
21
|
+
# Ordinary module over-ride to CatalogController
|
22
|
+
CatalogController.send(:include,
|
23
|
+
BlacklightAdvancedSearch::Controller
|
24
|
+
) unless
|
25
|
+
CatalogController.include?(
|
26
|
+
BlacklightAdvancedSearch::Controller
|
27
|
+
)
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
SearchHistoryController.send(:helper,
|
32
|
+
BlacklightAdvancedSearch::RenderConstraintsOverride
|
33
|
+
) unless
|
34
|
+
SearchHistoryController.helpers.is_a?(
|
35
|
+
BlacklightAdvancedSearch::RenderConstraintsOverride
|
36
|
+
)
|
37
|
+
|
38
|
+
SavedSearchesController.send(:helper,
|
39
|
+
BlacklightAdvancedSearch::RenderConstraintsOverride
|
40
|
+
) unless
|
41
|
+
SearchHistoryController.helpers.is_a?(
|
42
|
+
BlacklightAdvancedSearch::RenderConstraintsOverride
|
43
|
+
)
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module BlacklightAdvancedSearch::FilterParser
|
2
|
+
# Returns an array of solr :fq params. taking advanced search inclusive
|
3
|
+
# facet value lists out of params.
|
4
|
+
def generate_solr_fq
|
5
|
+
filter_queries = []
|
6
|
+
filters.each do |solr_field, value_list|
|
7
|
+
filter_queries << "#{solr_field}:(" +
|
8
|
+
value_list.collect {|v| '"' + v.gsub('"', '\"') +'"' }.join(" OR ") +
|
9
|
+
")"
|
10
|
+
end
|
11
|
+
return filter_queries
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'parsing_nesting/tree'
|
2
|
+
module BlacklightAdvancedSearch::ParsingNestingParser
|
3
|
+
|
4
|
+
def process_query(params,config)
|
5
|
+
queries = []
|
6
|
+
keyword_queries.each do |field,query|
|
7
|
+
queries << ParsingNesting::Tree.parse(query).to_query( local_param_hash(field) )
|
8
|
+
end
|
9
|
+
queries.join( ' ' + keyword_op + ' ')
|
10
|
+
end
|
11
|
+
|
12
|
+
def local_param_hash(key)
|
13
|
+
field_def = BlacklightAdvancedSearch.search_field_def_for_key(key)
|
14
|
+
|
15
|
+
(field_def[:solr_parameters] || {}).merge(field_def[:solr_local_parameters] || {})
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# Meant to be applied on top of Blacklight view helpers, to over-ride
|
2
|
+
# certain methods from RenderConstraintsHelper (newish in BL),
|
3
|
+
# to effect constraints rendering and search history rendering,
|
4
|
+
module BlacklightAdvancedSearch::RenderConstraintsOverride
|
5
|
+
|
6
|
+
#Over-ride of Blacklight method, provide advanced constraints if needed,
|
7
|
+
# otherwise call super. Existence of an @advanced_query instance variable
|
8
|
+
# is our trigger that we're in advanced mode.
|
9
|
+
def render_constraints_query(my_params = params)
|
10
|
+
if (@advanced_query.nil? || @advanced_query.keyword_queries.empty? )
|
11
|
+
return super(my_params)
|
12
|
+
else
|
13
|
+
content = ""
|
14
|
+
@advanced_query.keyword_queries.each_pair do |field, query|
|
15
|
+
label = BlacklightAdvancedSearch.search_field_def_for_key(field)[:display_label]
|
16
|
+
content << render_constraint_element(
|
17
|
+
label, query,
|
18
|
+
:remove =>
|
19
|
+
catalog_index_path(remove_advanced_keyword_query(field,my_params))
|
20
|
+
)
|
21
|
+
end
|
22
|
+
if (@advanced_query.keyword_op == "OR" &&
|
23
|
+
@advanced_query.keyword_queries.length > 1)
|
24
|
+
content = '<span class="inclusive_or appliedFilter">' + '<span class="operator">Any of:</span>' + content + '</span>'
|
25
|
+
end
|
26
|
+
|
27
|
+
return content
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
#Over-ride of Blacklight method, provide advanced constraints if needed,
|
32
|
+
# otherwise call super. Existence of an @advanced_query instance variable
|
33
|
+
# is our trigger that we're in advanced mode.
|
34
|
+
def render_constraints_filters(my_params = params)
|
35
|
+
content = super(my_params)
|
36
|
+
|
37
|
+
if (@advanced_query)
|
38
|
+
@advanced_query.filters.each_pair do |field, value_list|
|
39
|
+
label = Blacklight.config[:facet][:labels][field] or field.to_s.capitalize
|
40
|
+
content << render_constraint_element(label,
|
41
|
+
value_list.join(" OR "),
|
42
|
+
:remove => catalog_index_path( remove_advanced_filter_group(field, my_params) )
|
43
|
+
)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
return content
|
48
|
+
end
|
49
|
+
|
50
|
+
def render_search_to_s_filters(my_params)
|
51
|
+
content = super(my_params)
|
52
|
+
|
53
|
+
advanced_query = BlacklightAdvancedSearch::QueryParser.new(my_params, BlacklightAdvancedSearch.config )
|
54
|
+
|
55
|
+
if (advanced_query.filters.length > 0)
|
56
|
+
advanced_query.filters.each_pair do |field, values|
|
57
|
+
label = Blacklight.config[:facet][:labels][field] or field.to_s.capitalize
|
58
|
+
|
59
|
+
content << render_search_to_s_element(
|
60
|
+
label,
|
61
|
+
values.join(" OR ")
|
62
|
+
)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
return content
|
66
|
+
end
|
67
|
+
|
68
|
+
def render_search_to_s_q(my_params)
|
69
|
+
content = super(my_params)
|
70
|
+
|
71
|
+
advanced_query = BlacklightAdvancedSearch::QueryParser.new(my_params, BlacklightAdvancedSearch.config )
|
72
|
+
|
73
|
+
if (advanced_query.keyword_queries.length > 1 &&
|
74
|
+
advanced_query.keyword_op == "OR")
|
75
|
+
# Need to do something to make the inclusive-or search clear
|
76
|
+
|
77
|
+
display_as = advanced_query.keyword_queries.collect do |field, query|
|
78
|
+
h( BlacklightAdvancedSearch.search_field_def_for_key(field)[:display_label] + ": " + query )
|
79
|
+
end.join(" ; ")
|
80
|
+
|
81
|
+
content << render_search_to_s_element("Any of",
|
82
|
+
display_as,
|
83
|
+
:escape_value => false
|
84
|
+
)
|
85
|
+
elsif (advanced_query.keyword_queries.length > 0)
|
86
|
+
advanced_query.keyword_queries.each_pair do |field, query|
|
87
|
+
label = BlacklightAdvancedSearch.search_field_def_for_key(field)[:display_label]
|
88
|
+
|
89
|
+
content << render_search_to_s_element(label, query)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
return content
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module BlacklightAdvancedSearch
|
2
|
+
autoload :Controller, 'blacklight_advanced_search/controller'
|
3
|
+
autoload :RenderConstraintsOverride, 'blacklight_advanced_search/render_constraints_override'
|
4
|
+
autoload :CatalogHelperOverride, 'blacklight_advanced_search/catalog_helper_override'
|
5
|
+
autoload :QueryParser, 'blacklight_advanced_search/advanced_query_parser'
|
6
|
+
autoload :ParsingNestingParser, 'blacklight_advanced_search/parsing_nesting_parser'
|
7
|
+
autoload :FilterParser, 'blacklight_advanced_search/filter_parser'
|
8
|
+
|
9
|
+
require 'blacklight_advanced_search/version'
|
10
|
+
require 'blacklight_advanced_search/engine'
|
11
|
+
|
12
|
+
extend Blacklight::SearchFields # for search field config, so we can use same format as BL, or use ones already set in BL even.
|
13
|
+
|
14
|
+
# Has to be called in an after_initialize block, to have access
|
15
|
+
# to Blacklight.config already configured, to look at it for defaults.
|
16
|
+
def self.init
|
17
|
+
# apply defaults to anything not set.
|
18
|
+
BlacklightAdvancedSearch.config.reverse_merge!( BlacklightAdvancedSearch.config_defaults )
|
19
|
+
|
20
|
+
logger.info("BlacklightAdvancedSearch.config: initialized with: #{ config.inspect }")
|
21
|
+
Blacklight.config[:search_fields] << {:display_label => 'Advanced', :key => BlacklightAdvancedSearch.config[:url_key], :include_in_simple_select => false, :include_in_advanced_search => false} unless Blacklight.config[:search_fields].map { |x| x[:key] }.include? BlacklightAdvancedSearch.config[:url_key]
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.logger
|
25
|
+
RAILS_DEFAULT_LOGGER
|
26
|
+
end
|
27
|
+
|
28
|
+
# Hash of our config. The :search_fields key in hash is used by
|
29
|
+
# Blacklight::SearchFields module, must be an array of search field
|
30
|
+
# definitions compatible with that module, or if missing will
|
31
|
+
# inherit Blacklight.config[:search_fields]
|
32
|
+
def self.config
|
33
|
+
@config ||= {}
|
34
|
+
end
|
35
|
+
|
36
|
+
# Has to be called in an after_initialize, to make sure Blacklight.config
|
37
|
+
# is already defined.
|
38
|
+
def self.config_defaults
|
39
|
+
config = {}
|
40
|
+
config[:url_key] ||= "advanced"
|
41
|
+
config[:qt] ||= Blacklight.config[:default_qt] ||
|
42
|
+
(Blacklight.config[:default_solr_params] && Blacklight.config[:default_solr_params][:qt])
|
43
|
+
config[:form_solr_parameters] ||= {}
|
44
|
+
|
45
|
+
|
46
|
+
config[:search_fields] ||= Blacklight.config[:search_fields].find_all do |field_def|
|
47
|
+
(field_def[:qt].nil? || field_def[:qt] == config[:qt]) &&
|
48
|
+
field_def[:include_in_advanced_search] != false
|
49
|
+
end
|
50
|
+
|
51
|
+
config
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
def self.solr_local_params_for_search_field(key)
|
56
|
+
|
57
|
+
field_def = search_field_def_for_key(key)
|
58
|
+
|
59
|
+
solr_params = (field_def[:solr_parameters] || {}).merge(field_def[:solr_local_parameters] || {})
|
60
|
+
|
61
|
+
solr_params.collect do |key, val|
|
62
|
+
key.to_s + "=" + solr_param_quote(val)
|
63
|
+
end.join(" ")
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.solr_param_quote(val)
|
68
|
+
unless val =~ /^[a-zA-Z$_\-\^]+$/
|
69
|
+
val = "'" + val.gsub("'", "\\\'").gsub('"', "\\\"") + "'"
|
70
|
+
end
|
71
|
+
return val
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Copy BlacklightAdvancedSearch assets to public folder in current app.
|
2
|
+
# If you want to do this on application startup, you can
|
3
|
+
# add this next line to your one of your environment files --
|
4
|
+
# generally you'd only want to do this in 'development', and can
|
5
|
+
# add it to environments/development.rb:
|
6
|
+
# require File.join(BlacklightAdvancedSearch.root, "lib", "generators", "blacklight", "assets_generator.rb")
|
7
|
+
# BlacklightAdvancedSearch::AssetsGenerator.start(["--force", "--quiet"])
|
8
|
+
|
9
|
+
|
10
|
+
# Need the requires here so we can call the generator from environment.rb
|
11
|
+
# as suggested above.
|
12
|
+
require 'rails/generators'
|
13
|
+
require 'rails/generators/base'
|
14
|
+
module BlacklightAdvancedSearch
|
15
|
+
class AssetsGenerator < Rails::Generators::Base
|
16
|
+
source_root File.expand_path('../templates', __FILE__)
|
17
|
+
|
18
|
+
def assets
|
19
|
+
directory("public/stylesheets")
|
20
|
+
directory("public/javascripts")
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
class BlacklightAdvancedSearchGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
5
|
+
|
6
|
+
require File.expand_path('../assets_generator.rb', __FILE__)
|
7
|
+
def copy_public_assets
|
8
|
+
BlacklightAdvancedSearch::AssetsGenerator.start
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<div id="search" class="search">
|
2
|
+
<% form_tag catalog_index_path, :method => :get do %>
|
3
|
+
<h2 class="search"><%= label_tag(:q, "Search ") %></h2>
|
4
|
+
<%= text_field_tag :q, params[:q], :class => "q" %>
|
5
|
+
<%= label_tag(:search_field, " in ") %>
|
6
|
+
<%= select_tag(:search_field, options_for_select(search_fields, h(params[:search_field])), :title => "Targeted search options", :class=>"search_field") %>
|
7
|
+
|
8
|
+
<%= search_as_hidden_fields(:omit_keys => [:q, :search_field, :qt, :page]) %>
|
9
|
+
|
10
|
+
<%= submit_tag 'search', :class=>'submit' %>
|
11
|
+
<% end %>
|
12
|
+
<%= link_to 'More options', params.merge(:controller=>"advanced", :action=>"index") , :class=>"advanced_search"%>
|
13
|
+
</div>
|
@@ -0,0 +1,86 @@
|
|
1
|
+
##
|
2
|
+
# This example config file is set up to work using the Solr request handler
|
3
|
+
# called "advanced" in the example Blacklight solrconfig.xml:
|
4
|
+
# http://github.com/projectblacklight/blacklight-jetty/blob/master/solr/conf/solrconfig.xml
|
5
|
+
#
|
6
|
+
# NOTE WELL: Using a seperate request handler is just one option, in most cases
|
7
|
+
# it's simpler to use your default solr request handler set in Blacklight itself,
|
8
|
+
# in which case you would not want to set any of the configuration below!
|
9
|
+
# See README.
|
10
|
+
|
11
|
+
BlacklightAdvancedSearch.config.merge!(
|
12
|
+
# :search_field => "advanced", # name of key in Blacklight URL, no reason to change usually.
|
13
|
+
|
14
|
+
# Set advanced_parse_q to true to allow AND/OR/NOT in your basic/simple
|
15
|
+
# Blacklight search, parsed by Advanced Search Plugin.
|
16
|
+
#:advanced_parse_q => true,
|
17
|
+
|
18
|
+
:qt => "advanced" # name of Solr request handler, leave unset to use the same one as your Blacklight.config[:default_qt]
|
19
|
+
|
20
|
+
)
|
21
|
+
|
22
|
+
|
23
|
+
# You don't need to specify search_fields, if you leave :qt unspecified
|
24
|
+
# above, and have search field config in Blacklight already using that
|
25
|
+
# same qt, the plugin will simply use them. But if you'd like to use a
|
26
|
+
# different solr qt request handler, or have another reason for wanting
|
27
|
+
# to manually specify search fields, you can. Uses the hash format
|
28
|
+
# specified in Blacklight::SearchFields
|
29
|
+
|
30
|
+
BlacklightAdvancedSearch.config[:search_fields] = search_fields = []
|
31
|
+
search_fields << {
|
32
|
+
:key => 'author',
|
33
|
+
:solr_local_parameters => {
|
34
|
+
:pf => "$pf_author",
|
35
|
+
:qf => "$qf_author"
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
search_fields << {
|
40
|
+
:key => 'title',
|
41
|
+
:solr_local_parameters => {
|
42
|
+
:pf => "$pf_title",
|
43
|
+
:qf => "$qf_title"
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
search_fields << {
|
48
|
+
:key => 'subject',
|
49
|
+
:solr_local_parameters => {
|
50
|
+
:pf => "$pf_subject",
|
51
|
+
:qf => "$qf_subject"
|
52
|
+
}
|
53
|
+
}
|
54
|
+
|
55
|
+
search_fields << {
|
56
|
+
:key => 'keyword',
|
57
|
+
:solr_local_parameters => {
|
58
|
+
:pf => "$pf_keyword",
|
59
|
+
:qf => "$qf_keyword"
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
search_fields << {
|
64
|
+
:key => 'numbers',
|
65
|
+
:solr_local_parameters => {
|
66
|
+
:pf => "$pf_number",
|
67
|
+
:qf => "$qf_number"
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
##
|
72
|
+
# The advanced search form displays facets as a limit option.
|
73
|
+
# By default it will use whatever facets, if any, are returned
|
74
|
+
# by the Solr qt request handler in use. However, you can use
|
75
|
+
# this config option to have it request other facet params than
|
76
|
+
# default in the Solr request handler, in desired.
|
77
|
+
|
78
|
+
# BlacklightAdvancedSearch.config[:form_solr_parameters] = {
|
79
|
+
# "facet.field" => [
|
80
|
+
# "format",
|
81
|
+
# "lc_1letter_facet",
|
82
|
+
# "language_facet"
|
83
|
+
# ],
|
84
|
+
# "facet.limit" => -1, # all facet values
|
85
|
+
# "facet.sort" => "index" # sort by index value (alphabetically, more or less)
|
86
|
+
# }
|
@@ -0,0 +1,62 @@
|
|
1
|
+
$(document).ready(function() {
|
2
|
+
$('.limit_column ul').each(function(){
|
3
|
+
var ul = $(this);
|
4
|
+
// find all ul's that don't have any span descendants with a class of "selected"
|
5
|
+
if($('span.selected', ul).length == 0){
|
6
|
+
// hide it
|
7
|
+
ul.hide();
|
8
|
+
// attach the toggle behavior to the h3 tag
|
9
|
+
$('h3', ul.parent()).click(function(){
|
10
|
+
// toggle the next ul sibling
|
11
|
+
$(this).next('ul').slideToggle();
|
12
|
+
});
|
13
|
+
}
|
14
|
+
});
|
15
|
+
|
16
|
+
|
17
|
+
/* Stuff for handling the checkboxes */
|
18
|
+
/* When you click a checkbox, update readout */
|
19
|
+
|
20
|
+
|
21
|
+
/* Pass in a jquery obj holding the "selected facet element" spans, get back
|
22
|
+
a string for display representing currently checked things. */
|
23
|
+
function checkboxesToString(checkbox_elements) {
|
24
|
+
var selectedLabels = new Array();
|
25
|
+
checkbox_elements.each(function() {
|
26
|
+
if ($(this).is(":checked")) {
|
27
|
+
selectedLabels.push( $(this).next('label').text());
|
28
|
+
}
|
29
|
+
});
|
30
|
+
return selectedLabels.join(" OR ");
|
31
|
+
}
|
32
|
+
|
33
|
+
//Pass in JQuery object of zero or more <div class="facet_item"> blocks,
|
34
|
+
//that contain an h3, some checkboxes, and a span.adv_facet_selections for
|
35
|
+
//display of current selections. Will update the span.
|
36
|
+
function updateSelectedDisplay(facet_item) {
|
37
|
+
var checkboxes = $(facet_item).find("input:checkbox");
|
38
|
+
var displaySpan = $(facet_item).find("span.adv_facet_selections");
|
39
|
+
var displayStr = checkboxesToString( checkboxes );
|
40
|
+
|
41
|
+
displaySpan.text( displayStr );
|
42
|
+
if (displayStr == "") {
|
43
|
+
displaySpan.hide();
|
44
|
+
} else {
|
45
|
+
displaySpan.show();
|
46
|
+
}
|
47
|
+
|
48
|
+
|
49
|
+
}
|
50
|
+
|
51
|
+
// on page load, set initial properly
|
52
|
+
$(".facet_item").each(function() {
|
53
|
+
updateSelectedDisplay(this);
|
54
|
+
});
|
55
|
+
|
56
|
+
//change on checkbox change
|
57
|
+
$(".facet_item input:checkbox").change( function() {
|
58
|
+
updateSelectedDisplay( $(this).closest(".facet_item"));
|
59
|
+
});
|
60
|
+
|
61
|
+
|
62
|
+
});
|
data/lib/generators/blacklight_advanced_search/templates/public/stylesheets/advanced_results.css
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
/* Classes used for styling our custom components on the search results page */
|
2
|
+
|
3
|
+
/* constraints */
|
4
|
+
|
5
|
+
.inclusive_or .operator {
|
6
|
+
margin-right: 1em;
|
7
|
+
}
|
8
|
+
|
9
|
+
.inclusive_or .appliedFilter {
|
10
|
+
background-color: #F0F0F0;
|
11
|
+
}
|
12
|
+
|
13
|
+
/* making it match an h3 */
|
14
|
+
#appliedParams .inclusive_or .operator {
|
15
|
+
font-weight: bold;
|
16
|
+
color: #555555;
|
17
|
+
font-size: 108%;
|
18
|
+
}
|
19
|
+
|
20
|
+
/* Facet limit */
|
21
|
+
|
22
|
+
/* over-ride BL */
|
23
|
+
#facets .advanced_facet_limit ul {
|
24
|
+
border-bottom: none;
|
25
|
+
padding-bottom: 0;
|
26
|
+
}
|
27
|
+
|
28
|
+
|
29
|
+
.facet_limit .inclusive_or h4 {
|
30
|
+
margin-bottom: 0.5em;
|
31
|
+
}
|
32
|
+
|
33
|
+
.facet_limit .inclusive_or li {
|
34
|
+
margin-left: 1em;
|
35
|
+
}
|
36
|
+
|
37
|
+
/* optional link to search form */
|
38
|
+
.search .advanced_search {
|
39
|
+
font-size: 83.33%;
|
40
|
+
}
|
41
|
+
|