active_scaffold 3.0.23 → 3.0.24

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.
Files changed (62) hide show
  1. data/frontends/default/views/_action_group.html.erb +1 -1
  2. data/frontends/default/views/_action_group.html.erb~ +24 -0
  3. data/frontends/default/views/_form.html.erb~ +26 -0
  4. data/frontends/default/views/_form_association.html.erb~ +19 -0
  5. data/frontends/default/views/_form_association_footer.html.erb~ +16 -6
  6. data/frontends/default/views/_horizontal_subform.html.erb~ +29 -0
  7. data/frontends/default/views/_horizontal_subform_header.html.erb~ +3 -2
  8. data/frontends/default/views/_list_actions.html.erb~ +15 -0
  9. data/frontends/default/views/_list_inline_adapter.html.erb~ +10 -0
  10. data/frontends/default/views/_list_messages.html.erb~ +30 -0
  11. data/frontends/default/views/_list_pagination.html.erb~ +11 -0
  12. data/frontends/default/views/_list_pagination_links.html.erb~ +0 -0
  13. data/frontends/default/views/_render_field.js.erb~ +23 -0
  14. data/frontends/default/views/_row.html.erb~ +6 -0
  15. data/frontends/default/views/_vertical_subform.html.erb~ +12 -0
  16. data/frontends/default/views/edit_associated.js.erb~ +13 -0
  17. data/frontends/default/views/on_create.js.rjs +2 -2
  18. data/frontends/default/views/render_field.js.erb~ +1 -0
  19. data/lib/active_scaffold/actions/core.rb~ +13 -5
  20. data/lib/active_scaffold/actions/create.rb~ +149 -0
  21. data/lib/active_scaffold/actions/list.rb~ +196 -0
  22. data/lib/active_scaffold/actions/nested.rb +6 -2
  23. data/lib/active_scaffold/actions/nested.rb~ +252 -0
  24. data/lib/active_scaffold/actions/search.rb~ +49 -0
  25. data/lib/active_scaffold/actions/subform.rb~ +27 -0
  26. data/lib/active_scaffold/actions/update.rb~ +149 -0
  27. data/lib/active_scaffold/attribute_params.rb~ +202 -0
  28. data/lib/active_scaffold/bridges/record_select/{lib/record_select_bridge.rb~ → helpers.rb~} +7 -16
  29. data/lib/active_scaffold/bridges/shared/date_bridge.rb~ +209 -0
  30. data/lib/active_scaffold/config/create.rb +4 -4
  31. data/lib/active_scaffold/config/nested.rb +1 -0
  32. data/lib/active_scaffold/config/nested.rb~ +41 -0
  33. data/lib/active_scaffold/config/search.rb~ +74 -0
  34. data/lib/active_scaffold/constraints.rb~ +186 -0
  35. data/lib/active_scaffold/data_structures/action_columns.rb~ +140 -0
  36. data/lib/active_scaffold/data_structures/action_link.rb +4 -4
  37. data/lib/active_scaffold/data_structures/action_link.rb~ +179 -0
  38. data/lib/active_scaffold/data_structures/nested_info.rb~ +124 -0
  39. data/lib/active_scaffold/extensions/action_controller_rendering.rb~ +22 -0
  40. data/lib/active_scaffold/extensions/action_view_rendering.rb~ +108 -0
  41. data/lib/active_scaffold/extensions/cache_association.rb~ +12 -0
  42. data/lib/active_scaffold/extensions/reverse_associations.rb~ +64 -0
  43. data/lib/active_scaffold/extensions/routing_mapper.rb~ +34 -0
  44. data/lib/active_scaffold/extensions/unsaved_associated.rb~ +62 -0
  45. data/lib/active_scaffold/finder.rb~ +370 -0
  46. data/lib/active_scaffold/helpers/controller_helpers.rb~ +101 -0
  47. data/lib/active_scaffold/helpers/form_column_helpers.rb~ +321 -0
  48. data/lib/active_scaffold/helpers/id_helpers.rb~ +123 -0
  49. data/lib/active_scaffold/helpers/list_column_helpers.rb +9 -6
  50. data/lib/active_scaffold/helpers/list_column_helpers.rb~ +368 -0
  51. data/lib/active_scaffold/helpers/search_column_helpers.rb~ +94 -46
  52. data/lib/active_scaffold/helpers/view_helpers.rb +1 -1
  53. data/lib/active_scaffold/helpers/view_helpers.rb~ +353 -0
  54. data/lib/active_scaffold/version.rb +1 -1
  55. data/lib/active_scaffold.rb +1 -1
  56. data/lib/active_scaffold.rb~ +362 -0
  57. metadata +110 -76
  58. data/lib/active_scaffold/bridges/dragonfly/bridge.rb~ +0 -12
  59. data/lib/active_scaffold/bridges/dragonfly/lib/dragonfly_bridge.rb~ +0 -36
  60. data/lib/active_scaffold/bridges/dragonfly/lib/dragonfly_bridge_helpers.rb~ +0 -12
  61. data/lib/active_scaffold/bridges/dragonfly/lib/form_ui.rb~ +0 -27
  62. data/lib/active_scaffold/bridges/dragonfly/lib/list_ui.rb~ +0 -16
@@ -0,0 +1,368 @@
1
+ # coding: utf-8
2
+ module ActiveScaffold
3
+ module Helpers
4
+ # Helpers that assist with the rendering of a List Column
5
+ module ListColumnHelpers
6
+ def get_column_value(record, column)
7
+ begin
8
+ # check for an override helper
9
+ value = if column_override? column
10
+ # we only pass the record as the argument. we previously also passed the formatted_value,
11
+ # but mike perham pointed out that prohibited the usage of overrides to improve on the
12
+ # performance of our default formatting. see issue #138.
13
+ send(column_override(column), record)
14
+ # second, check if the dev has specified a valid list_ui for this column
15
+ elsif column.list_ui and override_column_ui?(column.list_ui)
16
+ send(override_column_ui(column.list_ui), column, record)
17
+ elsif column.column and override_column_ui?(column.column.type)
18
+ send(override_column_ui(column.column.type), column, record)
19
+ else
20
+ format_column_value(record, column)
21
+ end
22
+
23
+ value = ' '.html_safe if value.nil? or (value.respond_to?(:empty?) and value.empty?) # fix for IE 6
24
+ return value
25
+ rescue Exception => e
26
+ logger.error Time.now.to_s + "#{e.inspect} -- on the ActiveScaffold column = :#{column.name} in #{controller.class}"
27
+ raise e
28
+ end
29
+ end
30
+
31
+ # TODO: move empty_field_text and   logic in here?
32
+ # TODO: we need to distinguish between the automatic links *we* create and the ones that the dev specified. some logic may not apply if the dev specified the link.
33
+ def render_list_column(text, column, record)
34
+ if column.link
35
+ link = column.link
36
+ associated = record.send(column.association.name) if column.association
37
+ url_options = params_for(:action => nil, :id => record.id)
38
+
39
+ # setup automatic link
40
+ if column.autolink? && column.singular_association? # link to inline form
41
+ link = action_link_to_inline_form(column, record, associated, text)
42
+ return text if link.nil?
43
+ else
44
+ url_options[:link] = text
45
+ end
46
+
47
+ if column_link_authorized?(link, column, record, associated)
48
+ render_action_link(link, url_options, record)
49
+ else
50
+ "<a class='disabled'>#{text}</a>".html_safe
51
+ end
52
+ else
53
+ text = active_scaffold_inplace_edit(record, column, {:formatted_column => text}) if inplace_edit?(record, column)
54
+ text
55
+ end
56
+ end
57
+
58
+ # setup the action link to inline form
59
+ def action_link_to_inline_form(column, record, associated, text)
60
+ link = column.link.clone
61
+ link.label = text
62
+ if column.polymorphic_association?
63
+ polymorphic_controller = controller_path_for_activerecord(record.send(column.association.name).class)
64
+ return link if polymorphic_controller.nil?
65
+ link.controller = polymorphic_controller
66
+ end
67
+ configure_column_link(link, associated, column.actions_for_association_links)
68
+ end
69
+
70
+ def configure_column_link(link, associated, actions)
71
+ if column_empty?(associated) # if association is empty, we only can link to create form
72
+ if actions.include?(:new)
73
+ link.action = 'new'
74
+ link.crud_type = :create
75
+ link.label = as_(:create_new)
76
+ end
77
+ elsif actions.include?(:edit)
78
+ link.action = 'edit'
79
+ link.crud_type = :update
80
+ elsif actions.include?(:show)
81
+ link.action = 'show'
82
+ link.crud_type = :read
83
+ elsif actions.include?(:list)
84
+ link.action = 'index'
85
+ link.crud_type = :read
86
+ end
87
+ link if link.crud_type.present?
88
+ end
89
+
90
+ def column_link_authorized?(link, column, record, associated)
91
+ if column.association
92
+ associated_for_authorized = if associated.nil? || (associated.respond_to?(:blank?) && associated.blank?)
93
+ column.association.klass
94
+ elsif [:has_many, :has_and_belongs_to_many].include? column.association.macro
95
+ associated.first
96
+ else
97
+ associated
98
+ end
99
+ authorized = associated_for_authorized.authorized_for?(:crud_type => link.crud_type)
100
+ authorized = authorized and record.authorized_for?(:crud_type => :update, :column => column.name) if link.crud_type == :create
101
+ authorized
102
+ else
103
+ record.authorized_for?(:crud_type => link.crud_type)
104
+ end
105
+ end
106
+
107
+ # There are two basic ways to clean a column's value: h() and sanitize(). The latter is useful
108
+ # when the column contains *valid* html data, and you want to just disable any scripting. People
109
+ # can always use field overrides to clean data one way or the other, but having this override
110
+ # lets people decide which way it should happen by default.
111
+ #
112
+ # Why is it not a configuration option? Because it seems like a somewhat rare request. But it
113
+ # could eventually be an option in config.list (and config.show, I guess).
114
+ def clean_column_value(v)
115
+ h(v)
116
+ end
117
+
118
+ ##
119
+ ## Overrides
120
+ ##
121
+ def active_scaffold_column_text(column, record)
122
+ truncate(clean_column_value(record.send(column.name)), :length => column.options[:truncate] || 50)
123
+ end
124
+
125
+ def active_scaffold_column_checkbox(column, record)
126
+ options = {:disabled => true, :id => nil, :object => record}
127
+ options.delete(:disabled) if inplace_edit?(record, column)
128
+ check_box(:record, column.name, options)
129
+ end
130
+
131
+ def column_override_name(column, class_prefix = false)
132
+ "#{clean_class_name(column.active_record_class.name) + '_' if class_prefix}#{clean_column_name(column.name)}_column"
133
+ end
134
+
135
+ def column_override(column)
136
+ method_with_class = column_override_name(column, true)
137
+ return method_with_class if respond_to?(method_with_class)
138
+ method = column_override_name(column)
139
+ method if respond_to?(method)
140
+ end
141
+ alias_method :column_override?, :column_override
142
+
143
+ def override_column_ui?(list_ui)
144
+ respond_to?(override_column_ui(list_ui))
145
+ end
146
+
147
+ # the naming convention for overriding column types with helpers
148
+ def override_column_ui(list_ui)
149
+ "active_scaffold_column_#{list_ui}"
150
+ end
151
+
152
+ ##
153
+ ## Formatting
154
+ ##
155
+ def format_column_value(record, column, value = nil)
156
+ value ||= record.send(column.name) unless record.nil?
157
+ if value && column.association # cache association size before calling column_empty?
158
+ associated_size = value.size if column.plural_association? and column.associated_number? # get count before cache association
159
+ cache_association(value, column) if column.plural_association?
160
+ end
161
+ if column.association.nil? or column_empty?(value)
162
+ if column.form_ui == :select && column.options[:options]
163
+ text, val = column.options[:options].find {|text, val| (val.nil? ? text : val).to_s == value.to_s}
164
+ value = active_scaffold_translated_option(column, text, val).first if text
165
+ end
166
+ if value.is_a? Numeric
167
+ format_number_value(value, column.options)
168
+ else
169
+ format_value(value, column.options)
170
+ end
171
+ else
172
+ format_association_value(value, column, associated_size)
173
+ end
174
+ end
175
+
176
+ def format_number_value(value, options = {})
177
+ value = case options[:format]
178
+ when :size
179
+ number_to_human_size(value, options[:i18n_options] || {})
180
+ when :percentage
181
+ number_to_percentage(value, options[:i18n_options] || {})
182
+ when :currency
183
+ number_to_currency(value, options[:i18n_options] || {})
184
+ when :i18n_number
185
+ number_with_delimiter(value, options[:i18n_options] || {})
186
+ else
187
+ value
188
+ end
189
+ clean_column_value(value)
190
+ end
191
+
192
+ def format_association_value(value, column, size)
193
+ case column.association.macro
194
+ when :has_one, :belongs_to
195
+ if column.polymorphic_association?
196
+ format_value("#{value.class.model_name.human}: #{value.to_label}")
197
+ else
198
+ format_value(value.to_label)
199
+ end
200
+ when :has_many, :has_and_belongs_to_many
201
+ if column.associated_limit.nil?
202
+ firsts = value.collect { |v| clean_column_value(v.to_label) }
203
+ else
204
+ firsts = value.first(column.associated_limit)
205
+ firsts.collect! { |v| clean_column_value(v.to_label) }
206
+ firsts[column.associated_limit] = '…' if value.size > column.associated_limit
207
+ end
208
+ if column.associated_limit == 0
209
+ size if column.associated_number?
210
+ else
211
+ joined_associated = format_value(firsts.join(active_scaffold_config.list.association_join_text))
212
+ joined_associated << " (#{size})" if column.associated_number? and column.associated_limit and value.size > column.associated_limit
213
+ joined_associated
214
+ end
215
+ end
216
+ end
217
+
218
+ def format_value(column_value, options = {})
219
+ value = if column_empty?(column_value)
220
+ active_scaffold_config.list.empty_field_text
221
+ elsif column_value.is_a?(Time) || column_value.is_a?(Date)
222
+ l(column_value, :format => options[:format] || :default)
223
+ elsif [FalseClass, TrueClass].include?(column_value.class)
224
+ as_(column_value.to_s.to_sym)
225
+ else
226
+ column_value.to_s
227
+ end
228
+ clean_column_value(value)
229
+ end
230
+
231
+ def cache_association(value, column)
232
+ # we are not using eager loading, cache firsts records in order not to query the database in a future
233
+ unless value.loaded?
234
+ # load at least one record, is needed for column_empty? and checking permissions
235
+ if column.associated_limit.nil?
236
+ Rails.logger.warn "ActiveScaffold: Enable eager loading for #{column.name} association to reduce SQL queries"
237
+ else
238
+ value.target = value.find(:all, :limit => column.associated_limit + 1, :select => column.select_columns)
239
+ end
240
+ end
241
+ end
242
+
243
+ # ==========
244
+ # = Inline Edit =
245
+ # ==========
246
+
247
+ def inplace_edit?(record, column)
248
+ if column.inplace_edit
249
+ editable = controller.send(:update_authorized?, record) if controller.respond_to?(:update_authorized?)
250
+ editable = record.authorized_for?(:crud_type => :update, :column => column.name) if editable.nil? || editable == true
251
+ editable
252
+ end
253
+ end
254
+
255
+ def inplace_edit_cloning?(column)
256
+ column.inplace_edit != :ajax and (override_form_field?(column) or column.form_ui or (column.column and override_input?(column.column.type)))
257
+ end
258
+
259
+ def format_inplace_edit_column(record,column)
260
+ if column.list_ui == :checkbox
261
+ active_scaffold_column_checkbox(column, record)
262
+ else
263
+ format_column_value(record, column)
264
+ end
265
+ end
266
+
267
+ def active_scaffold_inplace_edit(record, column, options = {})
268
+ formatted_column = options[:formatted_column] || format_column_value(record, column)
269
+ id_options = {:id => record.id.to_s, :action => 'update_column', :name => column.name.to_s}
270
+ tag_options = {:id => element_cell_id(id_options), :class => "in_place_editor_field",
271
+ :title => as_(:click_to_edit), 'data-ie_id' => record.id.to_s}
272
+
273
+ content_tag(:span, formatted_column, tag_options)
274
+ end
275
+
276
+ def inplace_edit_control(column)
277
+ if inplace_edit?(active_scaffold_config.model, column) and inplace_edit_cloning?(column)
278
+ @record = new_model
279
+ column = column.clone
280
+ column.options = column.options.clone
281
+ column.form_ui = :select if (column.association && column.form_ui.nil?)
282
+ content_tag(:div, active_scaffold_input_for(column), {:style => "display:none;", :class => inplace_edit_control_css_class})
283
+ end
284
+ end
285
+
286
+ def inplace_edit_control_css_class
287
+ "as_inplace_pattern"
288
+ end
289
+
290
+ def inplace_edit_tag_attributes(column)
291
+ tag_options = {}
292
+ tag_options['data-ie_url'] = url_for({:controller => params_for[:controller], :action => "update_column", :column => column.name, :id => '__id__'})
293
+ tag_options['data-ie_cancel_text'] = column.options[:cancel_text] || as_(:cancel)
294
+ tag_options['data-ie_loading_text'] = column.options[:loading_text] || as_(:loading)
295
+ tag_options['data-ie_save_text'] = column.options[:save_text] || as_(:update)
296
+ tag_options['data-ie_saving_text'] = column.options[:saving_text] || as_(:saving)
297
+ tag_options['data-ie_rows'] = column.options[:rows] || 5 if column.column.try(:type) == :text
298
+ tag_options['data-ie_cols'] = column.options[:cols] if column.options[:cols]
299
+ tag_options['data-ie_size'] = column.options[:size] if column.options[:size]
300
+
301
+ if column.list_ui == :checkbox
302
+ tag_options['data-ie_mode'] = :inline_checkbox
303
+ elsif inplace_edit_cloning?(column)
304
+ tag_options['data-ie_mode'] = :clone
305
+ elsif column.inplace_edit == :ajax
306
+ url = url_for(:controller => params_for[:controller], :action => 'render_field', :id => '__id__', :column => column.name, :update_column => column.name, :in_place_editing => true, :escape => false)
307
+ plural = column.plural_association? && !override_form_field?(column) && [:select, :record_select].include?(column.form_ui)
308
+ tag_options['data-ie_render_url'] = url
309
+ tag_options['data-ie_mode'] = :ajax
310
+ tag_options['data-ie_plural'] = plural
311
+ end
312
+ tag_options
313
+ end
314
+
315
+ def mark_column_heading
316
+ if active_scaffold_config.mark.mark_all_mode == :page then
317
+ all_marked = true
318
+ @page.items.each do |record|
319
+ all_marked = false if !marked_records.entries.include?(record.id)
320
+ end
321
+ else
322
+ all_marked = (marked_records.length >= @page.pager.count)
323
+ end
324
+ tag_options = {:id => "#{controller_id}_mark_heading", :class => "mark_heading in_place_editor_field"}
325
+ tag_options['data-ie_url'] = url_for({:controller => params_for[:controller], :action => 'mark_all', :eid => params[:eid]})
326
+ content_tag(:span, check_box_tag("#{controller_id}_mark_heading_span_input", !all_marked, all_marked), tag_options)
327
+ end
328
+
329
+ def render_column_heading(column, sorting, sort_direction)
330
+ tag_options = {:id => active_scaffold_column_header_id(column), :class => column_heading_class(column, sorting), :title => column.description}
331
+ tag_options.merge!(inplace_edit_tag_attributes(column)) if column.inplace_edit
332
+ content_tag(:th, column_heading_value(column, sorting, sort_direction) + inplace_edit_control(column), tag_options)
333
+ end
334
+
335
+
336
+ def column_heading_value(column, sorting, sort_direction)
337
+ if column.sortable?
338
+ options = {:id => nil, :class => "as_sort",
339
+ 'data-page-history' => controller_id,
340
+ :remote => true, :method => :get}
341
+ url_options = params_for(:action => :index, :page => 1,
342
+ :sort => column.name, :sort_direction => sort_direction)
343
+ link_to column.label, url_options, options
344
+ else
345
+ if column.name != :marked
346
+ content_tag(:p, column.label)
347
+ else
348
+ mark_column_heading
349
+ end
350
+ end
351
+ end
352
+
353
+ def render_nested_view(action_links, url_options, record)
354
+ rendered = []
355
+ action_links.member.each do |link|
356
+ if link.nested_link? && link.column && @nested_auto_open[link.column.name] && @records.length <= @nested_auto_open[link.column.name] && controller.respond_to?(:render_component_into_view)
357
+ link_url_options = {:adapter => '_list_inline_adapter', :format => :js}.merge(action_link_url_options(link, url_options, record, options = {:reuse_eid => true}))
358
+ link_id = get_action_link_id(link_url_options, record, link.column)
359
+ rendered << (controller.send(:render_component_into_view, link_url_options) + javascript_tag("ActiveScaffold.ActionLink.get('#{link_id}').set_opened();"))
360
+ end
361
+ end
362
+ rendered.join(' ').html_safe
363
+ end
364
+
365
+ end
366
+ end
367
+ end
368
+
@@ -40,7 +40,7 @@ module ActiveScaffold
40
40
  # for textual fields we pass different options
41
41
  text_types = [:text, :string, :integer, :float, :decimal]
42
42
  options = active_scaffold_input_text_options(options) if text_types.include?(column.column.type)
43
- input(:record, column.name, options.merge(column.options))
43
+ text_field(:record, column.name, options.merge(column.options))
44
44
  end
45
45
  end
46
46
  end
@@ -59,37 +59,26 @@ module ActiveScaffold
59
59
  associated = options.delete :value
60
60
  associated = [associated].compact unless associated.is_a? Array
61
61
  associated.collect!(&:to_i)
62
- select_options = options_for_association(column.association, true)
63
- return as_(:no_options) if select_options.empty?
64
-
65
- html = "<ul class=\"checkbox-list\" id=\"#{options[:id]}\">"
66
-
67
- options[:name] += '[]'
68
- select_options.each_with_index do |option, i|
69
- label, id = option
70
- this_id = "#{options[:id]}_#{i}_id"
71
- html << "<li>"
72
- html << check_box_tag(options[:name], id, associated.include?(id), :id => this_id)
73
- html << "<label for='#{this_id}'>"
74
- html << label
75
- html << "</label>"
76
- html << "</li>"
62
+
63
+ if column.association
64
+ select_options = options_for_association(column.association, false)
65
+ else
66
+ select_options = Array(column.options[:options])
77
67
  end
68
+ return as_(:no_options) if select_options.empty?
78
69
 
79
- html << '</ul>'
80
- html << javascript_tag("new DraggableLists('#{options[:id]}')") if column.options[:draggable_lists]
81
- html
70
+ active_scaffold_checkbox_list(column, select_options, associated, options)
82
71
  end
83
72
 
84
73
  def active_scaffold_search_select(column, html_options)
85
74
  associated = html_options.delete :value
86
75
  if column.association
87
76
  associated = associated.is_a?(Array) ? associated.map(&:to_i) : associated.to_i unless associated.nil?
88
- method = column.association.macro == :belongs_to ? column.association.primary_key_name : column.name
89
- options_for_select = options_for_association(column.association, true)
77
+ method = column.association.macro == :belongs_to ? column.association.foreign_key : column.name
78
+ select_options = options_for_association(column.association, true)
90
79
  else
91
80
  method = column.name
92
- options_for_select = active_scaffold_translated_options(column)
81
+ select_options = Array(column.options[:options])
93
82
  end
94
83
 
95
84
  options = { :selected => associated }.merge! column.options
@@ -118,11 +107,43 @@ module ActiveScaffold
118
107
  end
119
108
  # we can't use checkbox ui because it's not possible to decide whether search for this field or not
120
109
  alias_method :active_scaffold_search_checkbox, :active_scaffold_search_boolean
110
+
111
+ def active_scaffold_search_null(column, options)
112
+ select_options = []
113
+ select_options << [as_(:_select_), nil]
114
+ select_options.concat ActiveScaffold::Finder::NullComparators.collect {|comp| [as_(comp), comp]}
115
+ select_tag(options[:name], options_for_select(select_options, field_search_params[column.name]))
116
+ end
121
117
 
122
118
  def field_search_params_range_values(column)
123
119
  values = field_search_params[column.name]
124
120
  return nil if values.nil?
125
- return values[:opt], values[:from], values[:to]
121
+ return values[:opt], (values[:from].blank? ? nil : values[:from]), (values[:to].blank? ? nil : values[:to])
122
+
123
+ end
124
+
125
+ def active_scaffold_search_range_string?(column)
126
+ (column.column && column.column.text?) || column.search_ui == :string
127
+ end
128
+
129
+ def include_null_comparators?(column)
130
+ return column.options[:null_comparators] if column.options.has_key? :null_comparators
131
+ if column.association
132
+ column.association.macro != :belongs_to || active_scaffold_config.columns[column.association.primary_key_name].column.try(:null)
133
+ else
134
+ column.column.try(:null)
135
+ end
136
+ end
137
+
138
+ def active_scaffold_search_range_comparator_options(column)
139
+ select_options = ActiveScaffold::Finder::NumericComparators.collect {|comp| [as_(comp.downcase.to_sym), comp]}
140
+ if active_scaffold_search_range_string?(column)
141
+ select_options.unshift *ActiveScaffold::Finder::StringComparators.collect {|title, comp| [as_(title), comp]}
142
+ end
143
+ if include_null_comparators? column
144
+ select_options += ActiveScaffold::Finder::NullComparators.collect {|comp| [as_(comp), comp]}
145
+ end
146
+ select_options
126
147
  end
127
148
 
128
149
  def include_null_comparators?(column)
@@ -136,20 +157,29 @@ module ActiveScaffold
136
157
 
137
158
  def active_scaffold_search_range(column, options)
138
159
  opt_value, from_value, to_value = field_search_params_range_values(column)
139
- select_options = ActiveScaffold::Finder::NumericComparators.collect {|comp| [as_(comp.downcase.to_sym), comp]}
140
- select_options.unshift *ActiveScaffold::Finder::StringComparators.collect {|title, comp| [as_(title), comp]} if column.options[:string_comparators] || column.column.try(:text?)
141
- select_options += ActiveScaffold::Finder::NullComparators.collect {|comp| [as_(comp.downcase.to_sym), comp]} if include_null_comparators? column
142
160
 
143
- html = []
144
- html << select_tag("#{options[:name]}[opt]",
161
+ select_options = active_scaffold_search_range_comparator_options(column)
162
+ if active_scaffold_search_range_string?(column)
163
+ text_field_size = 15
164
+ opt_value ||= '%?%'
165
+ else
166
+ text_field_size = 10
167
+ opt_value ||= '='
168
+ end
169
+
170
+ from_value = controller.class.condition_value_for_numeric(column, from_value)
171
+ to_value = controller.class.condition_value_for_numeric(column, to_value)
172
+ from_value = format_number_value(from_value, column.options) if from_value.is_a?(Numeric)
173
+ to_value = format_number_value(to_value, column.options) if to_value.is_a?(Numeric)
174
+ html = select_tag("#{options[:name]}[opt]",
145
175
  options_for_select(select_options, opt_value),
146
176
  :id => "#{options[:id]}_opt",
147
- :onchange => "Element[this.value == 'BETWEEN' ? 'show' : 'hide']('#{options[:id]}_between');")
148
- html << text_field_tag("#{options[:name]}[from]", from_value, active_scaffold_input_text_options(:id => options[:id], :size => 10))
149
- html << content_tag(:span, ' - ' + text_field_tag("#{options[:name]}[to]", to_value,
150
- active_scaffold_input_text_options(:id => "#{options[:id]}_to", :size => 10)),
151
- :id => "#{options[:id]}_between", :style => "display:none")
152
- html * ' '
177
+ :class => "as_search_range_option")
178
+ html << ' ' << text_field_tag("#{options[:name]}[from]", from_value, active_scaffold_input_text_options(:id => options[:id], :size => text_field_size))
179
+ html << ' ' << content_tag(:span, (' - ' + text_field_tag("#{options[:name]}[to]", to_value,
180
+ active_scaffold_input_text_options(:id => "#{options[:id]}_to", :size => text_field_size))).html_safe,
181
+ :id => "#{options[:id]}_between", :class => "as_search_range_between", :style => "display:#{(opt_value == 'BETWEEN') ? '' : 'none'}")
182
+ content_tag :span, html, :class => 'search_range'
153
183
  end
154
184
  alias_method :active_scaffold_search_integer, :active_scaffold_search_range
155
185
  alias_method :active_scaffold_search_decimal, :active_scaffold_search_range
@@ -164,10 +194,9 @@ module ActiveScaffold
164
194
  opt_value, from_value, to_value = field_search_params_range_values(column)
165
195
  options = column.options.merge(options)
166
196
  helper = "select_#{'date' unless options[:discard_date]}#{'time' unless options[:discard_time]}"
167
- html = []
168
- html << send(helper, field_search_datetime_value(from_value), {:include_blank => true, :prefix => "#{options[:name]}[from]"}.merge(options))
169
- html << send(helper, field_search_datetime_value(to_value), {:include_blank => true, :prefix => "#{options[:name]}[to]"}.merge(options))
170
- html * ' - '
197
+
198
+ send(helper, field_search_datetime_value(from_value), {:include_blank => true, :prefix => "#{options[:name]}[from]"}.merge(options)) <<
199
+ ' - '.html_safe << send(helper, field_search_datetime_value(to_value), {:include_blank => true, :prefix => "#{options[:name]}[to]"}.merge(options))
171
200
  end
172
201
 
173
202
  def active_scaffold_search_date(column, options)
@@ -183,16 +212,9 @@ module ActiveScaffold
183
212
  ##
184
213
 
185
214
  def override_search_field(column)
186
- method = override_search_field_name(column)
187
- return method if respond_to?(method)
188
- old_method = override_search_field_name(column, true)
189
- if respond_to?(old_method)
190
- ActiveSupport::Deprecation.warn("You are using an old naming schema for overrides, you should name the helper #{method} instead of #{old_method}")
191
- old_method
192
- end
193
215
  method_with_class = override_search_field_name(column, true)
194
216
  return method_with_class if respond_to?(method_with_class)
195
- method = override_form_field_name(column)
217
+ method = override_search_field_name(column)
196
218
  method if respond_to?(method)
197
219
  end
198
220
  alias_method :override_search_field?, :override_search_field
@@ -210,6 +232,32 @@ module ActiveScaffold
210
232
  def override_search(form_ui)
211
233
  "active_scaffold_search_#{form_ui}"
212
234
  end
235
+
236
+ def visibles_and_hiddens(search_config)
237
+ visibles = []
238
+ hiddens = []
239
+ search_config.columns.each do |column|
240
+ next unless column.search_sql
241
+ if search_config.optional_columns.include?(column.name) && !searched_by?(column)
242
+ hiddens << column
243
+ else
244
+ visibles << column
245
+ end
246
+ end
247
+ return visibles, hiddens
248
+ end
249
+
250
+ def searched_by?(column)
251
+ value = field_search_params[column.name]
252
+ case value
253
+ when Hash
254
+ !value['from'].blank?
255
+ when String
256
+ !value.blank?
257
+ else
258
+ false
259
+ end
260
+ end
213
261
  end
214
262
  end
215
263
  end
@@ -161,7 +161,7 @@ module ActiveScaffold
161
161
 
162
162
  def action_link_html_options(link, url_options, record, html_options)
163
163
  link_id = get_action_link_id(url_options, record, link.column)
164
- html_options.reverse_merge! link.html_options.merge(:class => link.action)
164
+ html_options.reverse_merge! link.html_options.merge(:class => link.action.to_s)
165
165
 
166
166
  # Needs to be in html_options to as the adding _method to the url is no longer supported by Rails
167
167
  html_options[:method] = link.method if link.method != :get