searchgasm 0.9.10 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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)