searchgasm 0.9.10 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +2 -0
- data/Manifest +10 -3
- data/README.rdoc +13 -9
- data/lib/searchgasm/config.rb +1 -78
- data/lib/searchgasm/helpers/control_types/link.rb +198 -0
- data/lib/searchgasm/helpers/control_types/links.rb +149 -0
- data/lib/searchgasm/helpers/control_types/remote_link.rb +86 -0
- data/lib/searchgasm/helpers/control_types/remote_links.rb +69 -0
- data/lib/searchgasm/helpers/control_types/remote_select.rb +33 -0
- data/lib/searchgasm/helpers/control_types/select.rb +78 -0
- data/lib/searchgasm/helpers/control_types.rb +41 -0
- data/lib/searchgasm/helpers/{form_helper.rb → form.rb} +51 -16
- data/lib/searchgasm/helpers/utilities.rb +59 -0
- data/lib/searchgasm/helpers.rb +3 -0
- data/lib/searchgasm/search/ordering.rb +1 -1
- data/lib/searchgasm/version.rb +3 -3
- data/lib/searchgasm.rb +8 -3
- data/searchgasm.gemspec +23 -9
- metadata +22 -8
- data/lib/searchgasm/helpers/search_helper.rb +0 -192
- data/lib/searchgasm/helpers/utilities_helper.rb +0 -125
@@ -1,192 +0,0 @@
|
|
1
|
-
module Searchgasm
|
2
|
-
module Helpers
|
3
|
-
# = Search Helper
|
4
|
-
#
|
5
|
-
# Helper methods for paginating and ordering through a search.
|
6
|
-
module SearchHelper
|
7
|
-
# Creates a link for ordering data in a certain way. See Searchgasm::Config for setting default configuration.
|
8
|
-
#
|
9
|
-
# === Example uses for a User class that has many orders
|
10
|
-
# order_by(:first_name)
|
11
|
-
# order_by([:first_name, :last_name])
|
12
|
-
# order_by({:orders => :total})
|
13
|
-
# order_bt([{:orders => :total}, :first_name])
|
14
|
-
#
|
15
|
-
# If the output just isn't cutting it for you, then you can pass it a block and it will spit out the result of the block. The block is passed "options" which is all of the information you should need
|
16
|
-
# for doing whatever you need to do. It's the options you are allowed to pass, but with their proper values.
|
17
|
-
#
|
18
|
-
# <%= order_by(:id) { |options| link_to(options[:text], options[:url], options[:html]) } %>
|
19
|
-
#
|
20
|
-
# or
|
21
|
-
#
|
22
|
-
# <% order_by(:id) do |options| %><%= link_to(options[:text], options[:url]) %><% end %>
|
23
|
-
#
|
24
|
-
# Another thing to keep in mind is that the value gets "serialized", if it is not a string or a simple, so that it can be passed via a param in the url. Searchgasm will automatically try to "unserializes" this value and use it. This allows you
|
25
|
-
# to pass complex objects besides strings and symbols, such as arrays and hashes.
|
26
|
-
#
|
27
|
-
# === Options
|
28
|
-
# * <tt>:text</tt> -- default: column_name.to_s.humanize, text for the link
|
29
|
-
# * <tt>:desc_indicator</tt> -- default: ▼, the indicator that this column is descending
|
30
|
-
# * <tt>:asc_indicator</tt> -- default: ▲, the indicator that this column is ascending
|
31
|
-
#
|
32
|
-
# === Advanced Options
|
33
|
-
# * <tt>:action</tt> -- this is automatically determined for you based on the type. For a :select type, its :onchange. For a :links type, its :onclick. You shouldn't have to use this option unless you are doing something out of the norm. The point of this option is to return a URL that will include this.value or not
|
34
|
-
# * <tt>:url</tt> -- default: uses url_for to preserve your params and search, I can not think of a reason to pass this, but its there just incase
|
35
|
-
# * <tt>:html</tt> -- if type is :links then these will apply to the outermost <div>, if type is :select then these will apply to the select tag
|
36
|
-
# * <tt>:search_obj</tt> -- default: @search, this is your search object, if it is in an instance variable other than @search please pass it here. Ex: :@my_search, or :my_search
|
37
|
-
# * <tt>:params_scope</tt> -- default: :search, this is the scope in which your search params will be preserved (params[:search]). If you don't want a scope and want your options to be at base leve in params such as params[:page], params[:per_page], etc, then set this to nil.
|
38
|
-
def order_by(column_name, options = {}, &block)
|
39
|
-
add_searchgasm_helper_defaults!(options, :order_by, column_name)
|
40
|
-
column_name = stringify_everything(column_name)
|
41
|
-
options[:text] = determine_order_by_text(column_name) unless options.has_key?(:text)
|
42
|
-
options[:asc_indicator] ||= Config.asc_indicator
|
43
|
-
options[:desc_indicator] ||= Config.desc_indicator
|
44
|
-
options[:text] += options[:search_obj].desc? ? options[:desc_indicator] : options[:asc_indicator] if options[:search_obj].order_by == column_name
|
45
|
-
|
46
|
-
if block_given?
|
47
|
-
yield options
|
48
|
-
else
|
49
|
-
if options[:remote]
|
50
|
-
link_to_function(options[:text], options[:url], options[:html])
|
51
|
-
else
|
52
|
-
link_to(options[:text], options[:url], options[:html])
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
# Creates navigation for paginating through a search. See Searchgasm::Config for setting default configuration.
|
58
|
-
#
|
59
|
-
# === Examples
|
60
|
-
# pages
|
61
|
-
# pages(:search => @my_search)
|
62
|
-
# pages(:html => {:id => "my_id"})
|
63
|
-
#
|
64
|
-
# If the output just isn't cutting it for you, then you can pass it a block and it will spit out the result of the block. The block is passed "options" which is all of the information you should need
|
65
|
-
# for doing whatever you need to do. It's the options you are allowed to pass, but with their proper values.
|
66
|
-
#
|
67
|
-
# <%= pages { |options| select(:search, :page, (1..options[:search_obj].page_count), {}, options[:html]) } %>
|
68
|
-
#
|
69
|
-
# or
|
70
|
-
#
|
71
|
-
# <% pages do |options| %><%= select(:search, :page, (1..options[:search_obj].page_count), {}, options[:html]) %><% end %>
|
72
|
-
#
|
73
|
-
# === Options
|
74
|
-
# * <tt>:type</tt> -- default: :select, pass :links as an alternative to have flickr like pagination
|
75
|
-
# * <tt>:remote</tt> -- default: false, if true requests will be AJAX
|
76
|
-
# * <tt>:text</tt> -- default: "1", "2", etc, if you want to change the text to say "Page 1", "Page 2", etc. Set this to: "Page %p". I will replace %p with the page #. Or pass a block and I will pass you the page number: Proc.new { |p| "Page #{p}" }
|
77
|
-
#
|
78
|
-
# === Advanced Options
|
79
|
-
# * <tt>:action</tt> -- this is automatically determined for you based on the type. For a :select type, its :onchange. For a :links type, its :onclick. You shouldn't have to use this option unless you are doing something out of the norm. The point of this option is to return a URL that will include this.value or not
|
80
|
-
# * <tt>:url</tt> -- default: uses url_for to preserve your params and search, I can not think of a reason to pass this, but its there just incase
|
81
|
-
# * <tt>:html</tt> -- if type is :links then these will apply to the outermost <div>, if type is :select then these will apply to the select tag
|
82
|
-
# * <tt>:search_obj</tt> -- default: @search, this is your search object, if it is in an instance variable other than @search please pass it here. Ex: :@my_search, or :my_search
|
83
|
-
# * <tt>:params_scope</tt> -- default: :search, this is the scope in which your search params will be preserved (params[:search]). If you don't want a scope and want your options to be at base leve in params such as params[:page], params[:per_page], etc, then set this to nil.
|
84
|
-
def pages(options = {})
|
85
|
-
options[:type] ||= Config.pages_type
|
86
|
-
add_searchgasm_helper_defaults!(options, :page)
|
87
|
-
return "" if options[:search_obj].page_count <= 1
|
88
|
-
|
89
|
-
page_range = (1..options[:search_obj].page_count)
|
90
|
-
options[:text] = Config.pages_text unless options.has_key?(:text)
|
91
|
-
|
92
|
-
choices = nil
|
93
|
-
case options[:text]
|
94
|
-
when String
|
95
|
-
choices = page_range.collect { |p| [options[:text].gsub(/%p/, p.to_s), p] }
|
96
|
-
when Proc
|
97
|
-
choices = page_range.collect { |p| [yield(p), p] }
|
98
|
-
else
|
99
|
-
choices = page_range
|
100
|
-
end
|
101
|
-
|
102
|
-
if block_given?
|
103
|
-
yield options
|
104
|
-
else
|
105
|
-
case options[:type]
|
106
|
-
when :select
|
107
|
-
options[:html] ||= {}
|
108
|
-
options[:html][options[:action]] ||= ""
|
109
|
-
options[:html][options[:action]] += ";"
|
110
|
-
options[:html][options[:action]] += options[:url]
|
111
|
-
select(options[:params_scope], :page, choices, {:selected => options[:search_obj].page}, options[:html])
|
112
|
-
else
|
113
|
-
# HTML for links
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
# Creates navigation for setting how many items per page. See Searchgasm::Config for setting default configuration.
|
119
|
-
#
|
120
|
-
# === Examples
|
121
|
-
# per_page
|
122
|
-
# per_page(:search => @my_search)
|
123
|
-
# per_page(:choices => [50, 100])
|
124
|
-
# per_page(:html => {:id => "my_id"})
|
125
|
-
#
|
126
|
-
# If the output just isn't cutting it for you, then you can pass it a block and it will spit out the result of the block. The block is passed "options" which is all of the information you should need
|
127
|
-
# for doing whatever you need to do. It's the options you are allowed to pass, but with their proper values.
|
128
|
-
#
|
129
|
-
# <%= per_page { |options| select(:search, :per_page, options[:choices], {}, options[:html]) } %>
|
130
|
-
#
|
131
|
-
# or
|
132
|
-
#
|
133
|
-
# <% per_page do |options| %><%= select(:search, :per_page, options[:choices], {}, options[:html]) %><% end %>
|
134
|
-
#
|
135
|
-
# === Options
|
136
|
-
# * <tt>:type</tt> -- default: :select, pass :links as an alternative to links like: 10 | 25 | 50 | 100, etc
|
137
|
-
# * <tt>:remote</tt> -- default: false, if true requests will be AJAX
|
138
|
-
# * <tt>:choices</tt> -- default: [10, 25, 50, 100, 150, 200, nil], nil means "show all"
|
139
|
-
#
|
140
|
-
# === Advanced Options
|
141
|
-
# * <tt>:choices</tt> -- default: [10, 25, 50, 100, 150, 200, nil], nil means "show all"
|
142
|
-
# * <tt>:action</tt> -- this is automatically determined for you based on the type. For a :select type, its :onchange. For a :links type, its :onclick. You shouldn't have to use this option unless you are doing something out of the norm. The point of this option is to return a URL that will include this.value or not
|
143
|
-
# * <tt>:url</tt> -- default: uses url_for to preserve your params and search, I can not think of a reason to pass this, but its there just incase
|
144
|
-
# * <tt>:html</tt> -- if type is :links then these will apply to the outermost <div>, if type is :select then these will apply to the select tag
|
145
|
-
# * <tt>:search_obj</tt> -- default: @search, this is your search object, if it is in an instance variable other than @search please pass it here. Ex: :@my_search, or :my_search
|
146
|
-
# * <tt>:params_scope</tt> -- default: :search, this is the scope in which your search params will be preserved (params[:search]). If you don't want a scope and want your options to be at base leve in params such as params[:page], params[:per_page], etc, then set this to nil.
|
147
|
-
def per_page(options = {})
|
148
|
-
options[:type] ||= Config.per_page_type
|
149
|
-
add_searchgasm_helper_defaults!(options, :per_page)
|
150
|
-
|
151
|
-
options[:choices] ||= Config.per_page_choices
|
152
|
-
if !options[:search_obj].per_page.blank? && !options[:choices].include?(options[:search_obj].per_page)
|
153
|
-
options[:choices] << options[:search_obj].per_page
|
154
|
-
has_nil = options[:choices].include?(nil)
|
155
|
-
options[:choices].delete(nil) if has_nil
|
156
|
-
options[:choices].sort!
|
157
|
-
options[:choices] << nil if has_nil
|
158
|
-
end
|
159
|
-
options[:choices] = options[:choices].collect { |choice| [choice == nil ? "Show all" : "#{choice} per page", choice] }
|
160
|
-
|
161
|
-
if block_given?
|
162
|
-
yield options
|
163
|
-
else
|
164
|
-
case options[:type]
|
165
|
-
when :select
|
166
|
-
options[:html] ||= {}
|
167
|
-
options[:html][options[:action]] ||= ""
|
168
|
-
options[:html][options[:action]] += ";"
|
169
|
-
options[:html][options[:action]] += options[:url]
|
170
|
-
select(options[:params_scope], :per_page, options[:choices], {:selected => options[:search_obj].per_page}, options[:html])
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
private
|
176
|
-
def determine_order_by_text(column_name, relationship_name = nil)
|
177
|
-
case column_name
|
178
|
-
when String, Symbol
|
179
|
-
relationship_name.blank? ? column_name.titleize : "#{relationship_name.titleize} #{column_name.titleize}"
|
180
|
-
when Array
|
181
|
-
determine_order_by_text(column_name.first)
|
182
|
-
when Hash
|
183
|
-
k = column_name.keys.first
|
184
|
-
v = column_name.values.first
|
185
|
-
determine_order_by_text(v, k)
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
ActionController::Base.helper Searchgasm::Helpers::SearchHelper if defined?(ActionController)
|
@@ -1,125 +0,0 @@
|
|
1
|
-
module Searchgasm
|
2
|
-
module Helpers #:nodoc:
|
3
|
-
module UtilitiesHelper # :nodoc:
|
4
|
-
private
|
5
|
-
# Adds default options for all helper methods.
|
6
|
-
def add_searchgasm_helper_defaults!(options, method_name, method_value = nil)
|
7
|
-
options[:search_obj] ||= instance_variable_get(Config.search_obj_name)
|
8
|
-
raise(ArgumentError, "@search object could not be inferred, please specify: :search_obj => @search)") unless options[:search_obj].is_a?(Searchgasm::Search::Base)
|
9
|
-
method_value = stringify_everything(method_value) unless method_value.nil?
|
10
|
-
options[:params_scope] = :search unless options.has_key?(:params_scope)
|
11
|
-
options[:remote] = Config.remote_helpers? unless options.has_key?(:remote)
|
12
|
-
|
13
|
-
if !options.has_key?(:action)
|
14
|
-
if options[:type] == :select
|
15
|
-
options[:action] = :onchange
|
16
|
-
elsif options[:remote]
|
17
|
-
options[:action] = :onclick
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
options[:url] = searchgasm_url(options, method_name, method_value) unless options.has_key?(:url)
|
22
|
-
|
23
|
-
options
|
24
|
-
end
|
25
|
-
|
26
|
-
def searchgasm_url(options, method_name, method_value = nil)
|
27
|
-
params = (params || {}).dup
|
28
|
-
params.delete(:commit)
|
29
|
-
|
30
|
-
# Extract search params from params
|
31
|
-
search_params = options[:params_scope].blank? ? params : params[options[:params_scope]] ||= {}
|
32
|
-
|
33
|
-
# Rewrite :order_by and :per_page with what's in our search obj
|
34
|
-
([:order_by, :per_page] - [method_name]).each { |search_option| search_params[search_option] = options[:search_obj].send(search_option) }
|
35
|
-
|
36
|
-
# Rewrite :conditions, separated due to unique call
|
37
|
-
conditions = options[:search_obj].conditions.conditions
|
38
|
-
search_params[:conditions] = conditions unless conditions.blank?
|
39
|
-
|
40
|
-
# Never want to keep page or the option we are trying to set
|
41
|
-
[:page, method_name].each { |option| search_params.delete(option) }
|
42
|
-
|
43
|
-
# Alternate :order_by if we are ordering
|
44
|
-
if method_name == :order_by
|
45
|
-
search_params[:order_as] = (options[:search_obj].order_by == method_value && options[:search_obj].asc?) ? "DESC" : "ASC"
|
46
|
-
else
|
47
|
-
search_params[:order_as] = options[:search_obj].order_as
|
48
|
-
end
|
49
|
-
|
50
|
-
# Determine if this.value should be included or not, and set up url
|
51
|
-
url = nil
|
52
|
-
case options[:action]
|
53
|
-
when :onchange
|
54
|
-
# Include this.value
|
55
|
-
url = url_for(params)
|
56
|
-
url_option = CGI.escape((options[:params_scope].blank? ? "#{method_name}" : "#{options[:params_scope]}[#{method_name}]")) + "='+this.value"
|
57
|
-
url += (url.last == "?" ? "" : (url.include?("?") ? "&" : "?")) + url_option
|
58
|
-
else
|
59
|
-
# Build the plain URL
|
60
|
-
search_params[method_name] = method_name == :order_by ? searchgasm_order_by_value(method_value) : method_value
|
61
|
-
url = url_for(params)
|
62
|
-
end
|
63
|
-
|
64
|
-
# Now update options if remote
|
65
|
-
if options[:remote]
|
66
|
-
url = remote_function(:url => url, :method => :get).gsub(/\\'\+this.value'/, "'+this.value") + ";"
|
67
|
-
|
68
|
-
update_fields = {method_name => method_value}
|
69
|
-
update_fields[:order_as] = search_params[:order_as] if method_name == :order_by
|
70
|
-
update_fields.each { |field, value| url += ";" + searchgasm_update_search_field_javascript(field, value, options) }
|
71
|
-
elsif !options[:action].blank?
|
72
|
-
# Add some javascript if its onclick
|
73
|
-
url = "window.location = '" + url + ";"
|
74
|
-
end
|
75
|
-
|
76
|
-
url
|
77
|
-
end
|
78
|
-
|
79
|
-
def searchgasm_update_search_field_javascript(field, value, options)
|
80
|
-
field_value = nil
|
81
|
-
|
82
|
-
case options[:action]
|
83
|
-
when :onchange
|
84
|
-
field_value = "this.value";
|
85
|
-
else
|
86
|
-
field_value = field == :order_by ? searchgasm_order_by_value(value) : value
|
87
|
-
field_value = "'#{CGI.escape(field_value)}'"
|
88
|
-
end
|
89
|
-
|
90
|
-
field_name = options[:params_scope] ? "#{options[:params_scope]}[#{field}]" : "#{field}"
|
91
|
-
"#{field} = $('#{searchgasm_form_id(options[:search_obj])}').getInputs('hidden', '#{field_name}'); if(#{field}.length > 0) { #{field}[0].value = #{field_value}; }"
|
92
|
-
end
|
93
|
-
|
94
|
-
def searchgasm_form_id(search_obj)
|
95
|
-
"#{search_obj.klass.name.pluralize.underscore}_search_form"
|
96
|
-
end
|
97
|
-
|
98
|
-
def searchgasm_order_by_value(order_by)
|
99
|
-
case order_by
|
100
|
-
when String
|
101
|
-
order_by
|
102
|
-
when Array, Hash
|
103
|
-
[Marshal.dump(order_by)].pack("m")
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
def stringify_everything(obj)
|
108
|
-
case obj
|
109
|
-
when String
|
110
|
-
obj
|
111
|
-
when Symbol
|
112
|
-
obj = obj.to_s
|
113
|
-
when Array
|
114
|
-
obj = obj.collect { |item| stringify_everything(item) }
|
115
|
-
when Hash
|
116
|
-
new_obj = {}
|
117
|
-
obj.each { |key, value| new_obj[key.to_s] = stringify_everything(value) }
|
118
|
-
new_obj
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
ActionController::Base.helper(Searchgasm::Helpers::UtilitiesHelper) if defined?(ActionController)
|