searchgasm 0.9.10 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: &nbsp;&#9660;, the indicator that this column is descending
30
- # * <tt>:asc_indicator</tt> -- default: &nbsp;&#9650;, 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?("?") ? "&amp;" : "?")) + 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)