active_scaffold_vho 3.0.6

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 (279) hide show
  1. data/.autotest +27 -0
  2. data/.document +5 -0
  3. data/CHANGELOG +179 -0
  4. data/Gemfile +13 -0
  5. data/Gemfile.lock +20 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README +63 -0
  8. data/Rakefile +53 -0
  9. data/frontends/default/images/add.gif +0 -0
  10. data/frontends/default/images/arrow_down.gif +0 -0
  11. data/frontends/default/images/arrow_up.gif +0 -0
  12. data/frontends/default/images/close.gif +0 -0
  13. data/frontends/default/images/config.png +0 -0
  14. data/frontends/default/images/cross.png +0 -0
  15. data/frontends/default/images/gears.png +0 -0
  16. data/frontends/default/images/indicator-small.gif +0 -0
  17. data/frontends/default/images/indicator.gif +0 -0
  18. data/frontends/default/images/magnifier.png +0 -0
  19. data/frontends/default/javascripts/jquery/active_scaffold.js +957 -0
  20. data/frontends/default/javascripts/jquery/jquery.editinplace.js +743 -0
  21. data/frontends/default/javascripts/prototype/active_scaffold.js +957 -0
  22. data/frontends/default/javascripts/prototype/dhtml_history.js +867 -0
  23. data/frontends/default/javascripts/prototype/form_enhancements.js +117 -0
  24. data/frontends/default/javascripts/prototype/rico_corner.js +370 -0
  25. data/frontends/default/stylesheets/stylesheet-ie.css +35 -0
  26. data/frontends/default/stylesheets/stylesheet.css +964 -0
  27. data/frontends/default/views/_action_group.html.erb +20 -0
  28. data/frontends/default/views/_add_existing_form.html.erb +30 -0
  29. data/frontends/default/views/_base_form.html.erb +45 -0
  30. data/frontends/default/views/_create_form.html.erb +8 -0
  31. data/frontends/default/views/_create_form_on_list.html.erb +6 -0
  32. data/frontends/default/views/_field_search.html.erb +32 -0
  33. data/frontends/default/views/_form.html.erb +24 -0
  34. data/frontends/default/views/_form_association.html.erb +14 -0
  35. data/frontends/default/views/_form_association_footer.html.erb +40 -0
  36. data/frontends/default/views/_form_attribute.html.erb +15 -0
  37. data/frontends/default/views/_form_hidden_attribute.html.erb +2 -0
  38. data/frontends/default/views/_form_messages.html.erb +5 -0
  39. data/frontends/default/views/_horizontal_subform.html.erb +19 -0
  40. data/frontends/default/views/_horizontal_subform_header.html.erb +10 -0
  41. data/frontends/default/views/_horizontal_subform_record.html.erb +37 -0
  42. data/frontends/default/views/_human_conditions.html.erb +1 -0
  43. data/frontends/default/views/_list.html.erb +18 -0
  44. data/frontends/default/views/_list_actions.html.erb +15 -0
  45. data/frontends/default/views/_list_calculations.html.erb +16 -0
  46. data/frontends/default/views/_list_column_headings.html.erb +12 -0
  47. data/frontends/default/views/_list_header.html.erb +10 -0
  48. data/frontends/default/views/_list_inline_adapter.html.erb +10 -0
  49. data/frontends/default/views/_list_messages.html.erb +32 -0
  50. data/frontends/default/views/_list_pagination.html.erb +11 -0
  51. data/frontends/default/views/_list_pagination_links.html.erb +9 -0
  52. data/frontends/default/views/_list_record.html.erb +14 -0
  53. data/frontends/default/views/_list_record_columns.html.erb +8 -0
  54. data/frontends/default/views/_list_with_header.html.erb +32 -0
  55. data/frontends/default/views/_messages.html.erb +10 -0
  56. data/frontends/default/views/_render_field.js.rjs +13 -0
  57. data/frontends/default/views/_row.html.erb +12 -0
  58. data/frontends/default/views/_search.html.erb +34 -0
  59. data/frontends/default/views/_search_attribute.html.erb +10 -0
  60. data/frontends/default/views/_show.html.erb +8 -0
  61. data/frontends/default/views/_show_columns.html.erb +15 -0
  62. data/frontends/default/views/_update_actions.html.erb +9 -0
  63. data/frontends/default/views/_update_form.html.erb +6 -0
  64. data/frontends/default/views/_vertical_subform.html.erb +12 -0
  65. data/frontends/default/views/_vertical_subform_record.html.erb +38 -0
  66. data/frontends/default/views/action_confirmation.html.erb +13 -0
  67. data/frontends/default/views/add_existing.js.rjs +17 -0
  68. data/frontends/default/views/add_existing_form.html.erb +5 -0
  69. data/frontends/default/views/create.html.erb +5 -0
  70. data/frontends/default/views/delete.html.erb +13 -0
  71. data/frontends/default/views/destroy.js.rjs +11 -0
  72. data/frontends/default/views/edit_associated.js.rjs +11 -0
  73. data/frontends/default/views/field_search.html.erb +5 -0
  74. data/frontends/default/views/form_messages.js.rjs +1 -0
  75. data/frontends/default/views/list.html.erb +1 -0
  76. data/frontends/default/views/list.js.rjs +1 -0
  77. data/frontends/default/views/on_action_update.js.rjs +8 -0
  78. data/frontends/default/views/on_create.js.rjs +41 -0
  79. data/frontends/default/views/on_update.js.rjs +28 -0
  80. data/frontends/default/views/search.html.erb +5 -0
  81. data/frontends/default/views/show.html.erb +5 -0
  82. data/frontends/default/views/update.html.erb +8 -0
  83. data/frontends/default/views/update_column.js.rjs +13 -0
  84. data/frontends/default/views/update_row.js.rjs +1 -0
  85. data/init.rb +9 -0
  86. data/lib/active_record_permissions.rb +134 -0
  87. data/lib/active_scaffold/actions/common_search.rb +22 -0
  88. data/lib/active_scaffold/actions/core.rb +170 -0
  89. data/lib/active_scaffold/actions/create.rb +145 -0
  90. data/lib/active_scaffold/actions/delete.rb +75 -0
  91. data/lib/active_scaffold/actions/field_search.rb +82 -0
  92. data/lib/active_scaffold/actions/list.rb +184 -0
  93. data/lib/active_scaffold/actions/mark.rb +50 -0
  94. data/lib/active_scaffold/actions/nested.rb +250 -0
  95. data/lib/active_scaffold/actions/search.rb +47 -0
  96. data/lib/active_scaffold/actions/show.rb +61 -0
  97. data/lib/active_scaffold/actions/subform.rb +17 -0
  98. data/lib/active_scaffold/actions/update.rb +141 -0
  99. data/lib/active_scaffold/attribute_params.rb +207 -0
  100. data/lib/active_scaffold/bridges/ancestry/bridge.rb +5 -0
  101. data/lib/active_scaffold/bridges/ancestry/lib/ancestry_bridge.rb +39 -0
  102. data/lib/active_scaffold/bridges/bridge.rb +52 -0
  103. data/lib/active_scaffold/bridges/calendar_date_select/bridge.rb +16 -0
  104. data/lib/active_scaffold/bridges/calendar_date_select/lib/as_cds_bridge.rb +79 -0
  105. data/lib/active_scaffold/bridges/carrierwave/bridge.rb +7 -0
  106. data/lib/active_scaffold/bridges/carrierwave/lib/carrierwave_bridge.rb +38 -0
  107. data/lib/active_scaffold/bridges/carrierwave/lib/carrierwave_bridge_helpers.rb +26 -0
  108. data/lib/active_scaffold/bridges/carrierwave/lib/form_ui.rb +35 -0
  109. data/lib/active_scaffold/bridges/carrierwave/lib/list_ui.rb +17 -0
  110. data/lib/active_scaffold/bridges/date_picker/bridge.rb +22 -0
  111. data/lib/active_scaffold/bridges/date_picker/lib/datepicker_bridge.rb +225 -0
  112. data/lib/active_scaffold/bridges/date_picker/public/javascripts/date_picker_bridge.js +22 -0
  113. data/lib/active_scaffold/bridges/file_column/bridge.rb +11 -0
  114. data/lib/active_scaffold/bridges/file_column/lib/as_file_column_bridge.rb +46 -0
  115. data/lib/active_scaffold/bridges/file_column/lib/file_column_helpers.rb +59 -0
  116. data/lib/active_scaffold/bridges/file_column/lib/form_ui.rb +37 -0
  117. data/lib/active_scaffold/bridges/file_column/lib/list_ui.rb +26 -0
  118. data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +43 -0
  119. data/lib/active_scaffold/bridges/file_column/test/mock_model.rb +9 -0
  120. data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +15 -0
  121. data/lib/active_scaffold/bridges/paperclip/bridge.rb +10 -0
  122. data/lib/active_scaffold/bridges/paperclip/lib/form_ui.rb +27 -0
  123. data/lib/active_scaffold/bridges/paperclip/lib/list_ui.rb +16 -0
  124. data/lib/active_scaffold/bridges/paperclip/lib/paperclip_bridge.rb +38 -0
  125. data/lib/active_scaffold/bridges/paperclip/lib/paperclip_bridge_helpers.rb +26 -0
  126. data/lib/active_scaffold/bridges/semantic_attributes/bridge.rb +5 -0
  127. data/lib/active_scaffold/bridges/semantic_attributes/lib/semantic_attributes_bridge.rb +20 -0
  128. data/lib/active_scaffold/bridges/shared/date_bridge.rb +187 -0
  129. data/lib/active_scaffold/bridges/tiny_mce/bridge.rb +5 -0
  130. data/lib/active_scaffold/bridges/tiny_mce/lib/tiny_mce_bridge.rb +45 -0
  131. data/lib/active_scaffold/bridges/validation_reflection/bridge.rb +8 -0
  132. data/lib/active_scaffold/bridges/validation_reflection/lib/validation_reflection_bridge.rb +21 -0
  133. data/lib/active_scaffold/config/base.rb +62 -0
  134. data/lib/active_scaffold/config/core.rb +220 -0
  135. data/lib/active_scaffold/config/create.rb +51 -0
  136. data/lib/active_scaffold/config/delete.rb +34 -0
  137. data/lib/active_scaffold/config/field_search.rb +75 -0
  138. data/lib/active_scaffold/config/form.rb +47 -0
  139. data/lib/active_scaffold/config/list.rb +174 -0
  140. data/lib/active_scaffold/config/mark.rb +22 -0
  141. data/lib/active_scaffold/config/nested.rb +44 -0
  142. data/lib/active_scaffold/config/search.rb +69 -0
  143. data/lib/active_scaffold/config/show.rb +35 -0
  144. data/lib/active_scaffold/config/subform.rb +35 -0
  145. data/lib/active_scaffold/config/update.rb +46 -0
  146. data/lib/active_scaffold/configurable.rb +29 -0
  147. data/lib/active_scaffold/constraints.rb +184 -0
  148. data/lib/active_scaffold/data_structures/action_columns.rb +133 -0
  149. data/lib/active_scaffold/data_structures/action_link.rb +171 -0
  150. data/lib/active_scaffold/data_structures/action_links.rb +175 -0
  151. data/lib/active_scaffold/data_structures/actions.rb +45 -0
  152. data/lib/active_scaffold/data_structures/column.rb +351 -0
  153. data/lib/active_scaffold/data_structures/columns.rb +75 -0
  154. data/lib/active_scaffold/data_structures/error_message.rb +24 -0
  155. data/lib/active_scaffold/data_structures/nested_info.rb +123 -0
  156. data/lib/active_scaffold/data_structures/set.rb +62 -0
  157. data/lib/active_scaffold/data_structures/sorting.rb +168 -0
  158. data/lib/active_scaffold/finder.rb +333 -0
  159. data/lib/active_scaffold/helpers/association_helpers.rb +40 -0
  160. data/lib/active_scaffold/helpers/controller_helpers.rb +82 -0
  161. data/lib/active_scaffold/helpers/country_helpers.rb +352 -0
  162. data/lib/active_scaffold/helpers/form_column_helpers.rb +347 -0
  163. data/lib/active_scaffold/helpers/human_condition_helpers.rb +59 -0
  164. data/lib/active_scaffold/helpers/id_helpers.rb +127 -0
  165. data/lib/active_scaffold/helpers/list_column_helpers.rb +361 -0
  166. data/lib/active_scaffold/helpers/pagination_helpers.rb +55 -0
  167. data/lib/active_scaffold/helpers/search_column_helpers.rb +243 -0
  168. data/lib/active_scaffold/helpers/show_column_helpers.rb +46 -0
  169. data/lib/active_scaffold/helpers/view_helpers.rb +356 -0
  170. data/lib/active_scaffold/locale/de.rb +120 -0
  171. data/lib/active_scaffold/locale/en.rb +119 -0
  172. data/lib/active_scaffold/locale/es.yml +115 -0
  173. data/lib/active_scaffold/locale/fr.rb +116 -0
  174. data/lib/active_scaffold/locale/hu.yml +63 -0
  175. data/lib/active_scaffold/locale/ja.yml +64 -0
  176. data/lib/active_scaffold/locale/ru.yml +119 -0
  177. data/lib/active_scaffold/marked_model.rb +38 -0
  178. data/lib/active_scaffold/version.rb +9 -0
  179. data/lib/active_scaffold.rb +345 -0
  180. data/lib/active_scaffold_assets.rb +45 -0
  181. data/lib/dhtml_confirm.rb +54 -0
  182. data/lib/environment.rb +14 -0
  183. data/lib/extensions/action_controller_rendering.rb +20 -0
  184. data/lib/extensions/action_view_rendering.rb +113 -0
  185. data/lib/extensions/action_view_resolver.rb +7 -0
  186. data/lib/extensions/active_association_reflection.rb +13 -0
  187. data/lib/extensions/active_record_offset.rb +12 -0
  188. data/lib/extensions/array.rb +7 -0
  189. data/lib/extensions/localize.rb +10 -0
  190. data/lib/extensions/name_option_for_datetime.rb +12 -0
  191. data/lib/extensions/nil_id_in_url_params.rb +7 -0
  192. data/lib/extensions/paginator_extensions.rb +26 -0
  193. data/lib/extensions/reverse_associations.rb +62 -0
  194. data/lib/extensions/routing_mapper.rb +34 -0
  195. data/lib/extensions/to_label.rb +8 -0
  196. data/lib/extensions/unsaved_associated.rb +61 -0
  197. data/lib/extensions/unsaved_record.rb +20 -0
  198. data/lib/extensions/usa_state.rb +46 -0
  199. data/lib/generators/active_scaffold/USAGE +29 -0
  200. data/lib/generators/active_scaffold/active_scaffold_generator.rb +20 -0
  201. data/lib/generators/active_scaffold_controller/USAGE +19 -0
  202. data/lib/generators/active_scaffold_controller/active_scaffold_controller_generator.rb +28 -0
  203. data/lib/generators/active_scaffold_controller/templates/controller.rb +4 -0
  204. data/lib/generators/active_scaffold_setup/USAGE +10 -0
  205. data/lib/generators/active_scaffold_setup/active_scaffold_setup_generator.rb +53 -0
  206. data/lib/paginator.rb +136 -0
  207. data/lib/responds_to_parent.rb +70 -0
  208. data/public/blank.html +33 -0
  209. data/shoulda_macros/macros.rb +136 -0
  210. data/test/bridges/bridge_test.rb +47 -0
  211. data/test/config/base_test.rb +15 -0
  212. data/test/config/create_test.rb +55 -0
  213. data/test/config/list_test.rb +74 -0
  214. data/test/config/show_test.rb +43 -0
  215. data/test/config/update_test.rb +17 -0
  216. data/test/const_mocker.rb +36 -0
  217. data/test/data_structures/action_columns_test.rb +113 -0
  218. data/test/data_structures/action_link_test.rb +78 -0
  219. data/test/data_structures/action_links_test.rb +78 -0
  220. data/test/data_structures/actions_test.rb +25 -0
  221. data/test/data_structures/association_column_test.rb +42 -0
  222. data/test/data_structures/column_test.rb +185 -0
  223. data/test/data_structures/columns_test.rb +69 -0
  224. data/test/data_structures/error_message_test.rb +28 -0
  225. data/test/data_structures/set_test.rb +86 -0
  226. data/test/data_structures/sorting_test.rb +126 -0
  227. data/test/data_structures/standard_column_test.rb +24 -0
  228. data/test/data_structures/virtual_column_test.rb +23 -0
  229. data/test/extensions/active_record_test.rb +45 -0
  230. data/test/extensions/array_test.rb +12 -0
  231. data/test/helpers/form_column_helpers_test.rb +31 -0
  232. data/test/helpers/list_column_helpers_test.rb +31 -0
  233. data/test/helpers/pagination_helpers_test.rb +55 -0
  234. data/test/misc/active_record_permissions_test.rb +154 -0
  235. data/test/misc/attribute_params_test.rb +110 -0
  236. data/test/misc/configurable_test.rb +96 -0
  237. data/test/misc/constraints_test.rb +193 -0
  238. data/test/misc/finder_test.rb +93 -0
  239. data/test/misc/lang_test.rb +12 -0
  240. data/test/mock_app/.gitignore +2 -0
  241. data/test/mock_app/app/controllers/application_controller.rb +10 -0
  242. data/test/mock_app/app/helpers/application_helper.rb +3 -0
  243. data/test/mock_app/config/boot.rb +110 -0
  244. data/test/mock_app/config/database.yml +16 -0
  245. data/test/mock_app/config/environment.rb +43 -0
  246. data/test/mock_app/config/environments/development.rb +17 -0
  247. data/test/mock_app/config/environments/production.rb +28 -0
  248. data/test/mock_app/config/environments/test.rb +28 -0
  249. data/test/mock_app/config/initializers/backtrace_silencers.rb +7 -0
  250. data/test/mock_app/config/initializers/inflections.rb +10 -0
  251. data/test/mock_app/config/initializers/mime_types.rb +5 -0
  252. data/test/mock_app/config/initializers/new_rails_defaults.rb +19 -0
  253. data/test/mock_app/config/initializers/session_store.rb +15 -0
  254. data/test/mock_app/config/locales/en.yml +5 -0
  255. data/test/mock_app/config/routes.rb +43 -0
  256. data/test/mock_app/db/test.sqlite3 +1 -0
  257. data/test/mock_app/public/blank.html +33 -0
  258. data/test/mock_app/public/images/active_scaffold/DO_NOT_EDIT +2 -0
  259. data/test/mock_app/public/images/active_scaffold/default/add.gif +0 -0
  260. data/test/mock_app/public/images/active_scaffold/default/arrow_down.gif +0 -0
  261. data/test/mock_app/public/images/active_scaffold/default/arrow_up.gif +0 -0
  262. data/test/mock_app/public/images/active_scaffold/default/close.gif +0 -0
  263. data/test/mock_app/public/images/active_scaffold/default/cross.png +0 -0
  264. data/test/mock_app/public/images/active_scaffold/default/indicator-small.gif +0 -0
  265. data/test/mock_app/public/images/active_scaffold/default/indicator.gif +0 -0
  266. data/test/mock_app/public/images/active_scaffold/default/magnifier.png +0 -0
  267. data/test/mock_app/public/javascripts/active_scaffold/DO_NOT_EDIT +2 -0
  268. data/test/mock_app/public/javascripts/active_scaffold/default/active_scaffold.js +532 -0
  269. data/test/mock_app/public/javascripts/active_scaffold/default/dhtml_history.js +867 -0
  270. data/test/mock_app/public/javascripts/active_scaffold/default/form_enhancements.js +117 -0
  271. data/test/mock_app/public/javascripts/active_scaffold/default/rico_corner.js +370 -0
  272. data/test/mock_app/public/stylesheets/active_scaffold/DO_NOT_EDIT +2 -0
  273. data/test/mock_app/public/stylesheets/active_scaffold/default/stylesheet-ie.css +35 -0
  274. data/test/mock_app/public/stylesheets/active_scaffold/default/stylesheet.css +839 -0
  275. data/test/model_stub.rb +55 -0
  276. data/test/run_all.rb +8 -0
  277. data/test/test_helper.rb +39 -0
  278. data/uninstall.rb +13 -0
  279. metadata +492 -0
@@ -0,0 +1,347 @@
1
+ module ActiveScaffold
2
+ module Helpers
3
+ # Helpers that assist with the rendering of a Form Column
4
+ module FormColumnHelpers
5
+ # This method decides which input to use for the given column.
6
+ # It does not do any rendering. It only decides which method is responsible for rendering.
7
+ def active_scaffold_input_for(column, scope = nil, options = {})
8
+ options = active_scaffold_input_options(column, scope, options)
9
+ options = update_columns_options(column, scope, options)
10
+ active_scaffold_render_input(column, options)
11
+ end
12
+
13
+ alias form_column active_scaffold_input_for
14
+
15
+ def active_scaffold_render_input(column, options)
16
+ begin
17
+ # first, check if the dev has created an override for this specific field
18
+ if override_form_field?(column)
19
+ send(override_form_field(column), @record, options)
20
+ # second, check if the dev has specified a valid form_ui for this column
21
+ elsif column.form_ui and override_input?(column.form_ui)
22
+ send(override_input(column.form_ui), column, options)
23
+ # fallback: we get to make the decision
24
+ else
25
+ if column.association
26
+ if column.form_ui.nil?
27
+ # its an association and nothing is specified, we will assume form_ui :select
28
+ active_scaffold_input_select(column, options)
29
+ else
30
+ # if we get here, it's because the column has a form_ui but not one ActiveScaffold knows about.
31
+ raise "Unknown form_ui `#{column.form_ui}' for column `#{column.name}'"
32
+ end
33
+ elsif column.virtual?
34
+ active_scaffold_input_virtual(column, options)
35
+
36
+ else # regular model attribute column
37
+ # if we (or someone else) have created a custom render option for the column type, use that
38
+ if override_input?(column.column.type)
39
+ send(override_input(column.column.type), column, options)
40
+ # final ultimate fallback: use rails' generic input method
41
+ else
42
+ # for textual fields we pass different options
43
+ text_types = [:text, :string, :integer, :float, :decimal, :date, :time, :datetime]
44
+ options = active_scaffold_input_text_options(options) if text_types.include?(column.column.type)
45
+ if column.column.type == :string && options[:maxlength].blank?
46
+ options[:maxlength] = column.column.limit
47
+ options[:size] ||= ActionView::Helpers::InstanceTag::DEFAULT_FIELD_OPTIONS["size"]
48
+ end
49
+ options[:include_blank] = true if column.column.null and [:date, :datetime, :time].include?(column.column.type)
50
+ options[:value] = format_number_value(@record.send(column.name), column.options) if column.column.number?
51
+ text_field(:record, column.name, options.merge(column.options))
52
+ end
53
+ end
54
+ end
55
+ rescue Exception => e
56
+ logger.error Time.now.to_s + "#{e.inspect} -- on the ActiveScaffold column = :#{column.name} in #{controller.class}"
57
+ raise e
58
+ end
59
+ end
60
+
61
+ # the standard active scaffold options used for textual inputs
62
+ def active_scaffold_input_text_options(options = {})
63
+ options[:autocomplete] = 'off'
64
+ options[:class] = "#{options[:class]} text-input".strip
65
+ options
66
+ end
67
+
68
+ # the standard active scaffold options used for class, name and scope
69
+ def active_scaffold_input_options(column, scope = nil, options = {})
70
+ name = scope ? "record#{scope}[#{column.name}]" : "record[#{column.name}]"
71
+
72
+ # Fix for keeping unique IDs in subform
73
+ id_control = "record_#{column.name}_#{[params[:eid], params[:id]].compact.join '_'}"
74
+ id_control += scope.gsub(/(\[|\])/, '_').gsub('__', '_').gsub(/_$/, '') if scope
75
+
76
+ { :name => name, :class => "#{column.name}-input", :id => id_control}.merge(options)
77
+ end
78
+
79
+ def update_columns_options(column, scope, options)
80
+ if column.update_columns
81
+ form_action = params[:action] == 'edit' ? :update : :create
82
+ url_params = {:action => 'render_field', :id => params[:id], :column => column.name, :update_columns => column.update_columns}
83
+ url_params[:eid] = params[:eid] if params[:eid]
84
+ url_params[:controller] = controller.class.active_scaffold_controller_for(@record.class).controller_path if scope
85
+ url_params[:scope] = params[:scope] if scope
86
+
87
+ options[:class] = "#{options[:class]} update_form".strip
88
+ options['data-update_url'] = url_for(url_params)
89
+ end
90
+ options
91
+ end
92
+
93
+ ##
94
+ ## Form input methods
95
+ ##
96
+
97
+ def active_scaffold_input_singular_association(column, html_options)
98
+ associated = @record.send(column.association.name)
99
+
100
+ select_options = options_for_association(column.association)
101
+ select_options.unshift([ associated.to_label, associated.id ]) unless associated.nil? or select_options.find {|label, id| id == associated.id}
102
+
103
+ selected = associated.nil? ? nil : associated.id
104
+ method = column.name
105
+ #html_options[:name] += '[id]'
106
+ options = {:selected => selected, :include_blank => as_(:_select_)}
107
+
108
+ html_options.update(column.options[:html_options] || {})
109
+ options.update(column.options)
110
+ select(:record, method, select_options.uniq, options, html_options)
111
+ end
112
+
113
+ def active_scaffold_input_plural_association(column, options)
114
+ associated_options = @record.send(column.association.name).collect {|r| [r.to_label, r.id]}
115
+ select_options = associated_options | options_for_association(column.association)
116
+ return content_tag(:span, as_(:no_options), :id => options[:id]) if select_options.empty?
117
+
118
+ active_scaffold_checkbox_list(column, select_options, associated_options.collect {|a| a[1]}, options)
119
+ end
120
+
121
+ def active_scaffold_checkbox_list(column, select_options, associated_ids, options)
122
+ html = "<ul class=\"checkbox-list\" id=\"#{options[:id]}\">"
123
+
124
+ select_options.each_with_index do |option, i|
125
+ label, id = option
126
+ this_id = "#{options[:id]}_#{i}_id"
127
+ html << content_tag(:li) do
128
+ check_box_tag("#{options[:name]}[]", id, associated_ids.include?(id), :id => this_id) <<
129
+ content_tag(:label, h(label), :for => this_id)
130
+ end
131
+ end
132
+ html << '</ul>'
133
+ html << javascript_tag("new DraggableLists('#{options[:id]}')") if column.options[:draggable_lists]
134
+ html.html_safe
135
+ end
136
+
137
+ def active_scaffold_translated_option(column, text, value = nil)
138
+ value ||= text
139
+ [(text.is_a?(Symbol) ? column.active_record_class.human_attribute_name(text) : text), value]
140
+ end
141
+
142
+ def active_scaffold_input_enum(column, html_options)
143
+ options = { :selected => @record.send(column.name) }
144
+ options_for_select = column.options[:options].collect do |text, value|
145
+ active_scaffold_translated_option(column, text, value)
146
+ end
147
+ html_options.update(column.options[:html_options] || {})
148
+ options.update(column.options)
149
+ select(:record, column.name, options_for_select, options, html_options)
150
+ end
151
+
152
+ def active_scaffold_input_select(column, html_options)
153
+ if column.singular_association?
154
+ active_scaffold_input_singular_association(column, html_options)
155
+ elsif column.plural_association?
156
+ active_scaffold_input_plural_association(column, html_options)
157
+ else
158
+ active_scaffold_input_enum(column, html_options)
159
+ end
160
+ end
161
+
162
+ def active_scaffold_input_radio(column, html_options)
163
+ html_options.update(column.options[:html_options] || {})
164
+ column.options[:options].inject('') do |html, (text, value)|
165
+ text, value = active_scaffold_translated_option(column, text, value)
166
+ html << content_tag(:label, radio_button(:record, column.name, value, html_options.merge(:id => html_options[:id] + '-' + value.to_s)) + text)
167
+ end.html_safe
168
+ end
169
+
170
+ # requires RecordSelect plugin to be installed and configured.
171
+ # ... maybe this should be provided in a bridge?
172
+ def active_scaffold_input_record_select(column, options)
173
+ if column.singular_association?
174
+ active_scaffold_record_select(column, options, @record.send(column.name), false)
175
+ elsif column.plural_association?
176
+ active_scaffold_record_select(column, options, @record.send(column.name), true)
177
+ end
178
+ end
179
+
180
+ def active_scaffold_record_select(column, options, value, multiple)
181
+ unless column.association
182
+ raise ArgumentError, "record_select can only work against associations (and #{column.name} is not). A common mistake is to specify the foreign key field (like :user_id), instead of the association (:user)."
183
+ end
184
+ remote_controller = active_scaffold_controller_for(column.association.klass).controller_path
185
+
186
+ # if the opposite association is a :belongs_to (in that case association in this class must be has_one or has_many)
187
+ # then only show records that have not been associated yet
188
+ if [:has_one, :has_many].include?(column.association.macro)
189
+ params.merge!({column.association.primary_key_name => ''})
190
+ end
191
+
192
+ record_select_options = {:controller => remote_controller, :id => options[:id]}
193
+ record_select_options.merge!(active_scaffold_input_text_options)
194
+ record_select_options.merge!(column.options)
195
+
196
+ if multiple
197
+ record_multi_select_field(options[:name], value || [], record_select_options)
198
+ else
199
+ record_select_field(options[:name], value || column.association.klass.new, record_select_options)
200
+ end
201
+ end
202
+
203
+ def active_scaffold_input_checkbox(column, options)
204
+ check_box(:record, column.name, options)
205
+ end
206
+
207
+ def active_scaffold_input_password(column, options)
208
+ options = active_scaffold_input_text_options(options)
209
+ password_field :record, column.name, options.merge(column.options)
210
+ end
211
+
212
+ def active_scaffold_input_textarea(column, options)
213
+ text_area(:record, column.name, options.merge(:cols => column.options[:cols], :rows => column.options[:rows], :size => column.options[:size]))
214
+ end
215
+
216
+ def active_scaffold_input_virtual(column, options)
217
+ options = active_scaffold_input_text_options(options)
218
+ text_field :record, column.name, options.merge(column.options)
219
+ end
220
+
221
+ #
222
+ # Column.type-based inputs
223
+ #
224
+
225
+ def active_scaffold_input_boolean(column, options)
226
+ select_options = []
227
+ select_options << [as_(:_select_), nil] if !column.virtual? && column.column.null
228
+ select_options << [as_(:true), true]
229
+ select_options << [as_(:false), false]
230
+
231
+ select_tag(options[:name], options_for_select(select_options, @record.send(column.name)), options)
232
+ end
233
+
234
+ def onsubmit
235
+ end
236
+
237
+ ##
238
+ ## Form column override signatures
239
+ ##
240
+
241
+ # add functionality for overriding subform partials from association class path
242
+ def override_subform_partial?(column, subform_partial)
243
+ path, partial_name = partial_pieces(override_subform_partial(column, subform_partial))
244
+ template_exists?(partial_name, path, true)
245
+ end
246
+
247
+ def override_subform_partial(column, subform_partial)
248
+ File.join(active_scaffold_controller_for(column.association.klass).controller_path, subform_partial) if column_renders_as(column) == :subform
249
+ end
250
+
251
+ def override_form_field_partial?(column)
252
+ path, partial_name = partial_pieces(override_form_field_partial(column))
253
+ template_exists?(partial_name, path, true)
254
+ end
255
+
256
+ # the naming convention for overriding form fields with partials
257
+ def override_form_field_partial(column)
258
+ "#{column.name}_form_column"
259
+ end
260
+
261
+ def override_form_field?(column)
262
+ respond_to?(override_form_field(column))
263
+ end
264
+
265
+ # the naming convention for overriding form fields with helpers
266
+ def override_form_field(column)
267
+ "#{column.name}_form_column"
268
+ end
269
+
270
+ def override_input?(form_ui)
271
+ respond_to?(override_input(form_ui))
272
+ end
273
+
274
+ # the naming convention for overriding form input types with helpers
275
+ def override_input(form_ui)
276
+ "active_scaffold_input_#{form_ui}"
277
+ end
278
+
279
+ def form_partial_for_column(column, renders_as = nil)
280
+ renders_as ||= column_renders_as(column)
281
+ if override_form_field_partial?(column)
282
+ override_form_field_partial(column)
283
+ elsif renders_as == :field or override_form_field?(column)
284
+ "form_attribute"
285
+ elsif renders_as == :subform
286
+ "form_association"
287
+ elsif renders_as == :hidden
288
+ "form_hidden_attribute"
289
+ end
290
+ end
291
+
292
+ def subform_partial_for_column(column)
293
+ subform_partial = "#{active_scaffold_config_for(column.association.klass).subform.layout}_subform"
294
+ if override_subform_partial?(column, subform_partial)
295
+ override_subform_partial(column, subform_partial)
296
+ else
297
+ subform_partial
298
+ end
299
+ end
300
+
301
+ ##
302
+ ## Macro-level rendering decisions for columns
303
+ ##
304
+
305
+ def column_renders_as(column)
306
+ if column.is_a? ActiveScaffold::DataStructures::ActionColumns
307
+ return :subsection
308
+ elsif column.active_record_class.locking_column.to_s == column.name.to_s or column.form_ui == :hidden
309
+ return :hidden
310
+ elsif column.association.nil? or column.form_ui or !active_scaffold_config_for(column.association.klass).actions.include?(:subform)
311
+ return :field
312
+ else
313
+ return :subform
314
+ end
315
+ end
316
+
317
+ def column_scope(column)
318
+ if column.plural_association?
319
+ "[#{column.name}][#{@record.id || generate_temporary_id}]"
320
+ else
321
+ "[#{column.name}]"
322
+ end
323
+ end
324
+
325
+ def active_scaffold_add_existing_input(options)
326
+ if ActiveScaffold.js_framework == :prototype && controller.respond_to?(:record_select_config)
327
+ remote_controller = active_scaffold_controller_for(record_select_config.model).controller_path
328
+ options.merge!(:controller => remote_controller)
329
+ options.merge!(active_scaffold_input_text_options)
330
+ record_select_field(options[:name], @record, options)
331
+ else
332
+ select_options = options_for_select(options_for_association(nested.association)) #unless column.through_association?
333
+ select_options ||= options_for_select(active_scaffold_config.model.all.collect {|c| [h(c.to_label), c.id]})
334
+ select_tag 'associated_id', ('<option value="">' + as_(:_select_) + '</option>' + select_options).html_safe unless select_options.empty?
335
+ end
336
+ end
337
+
338
+ def active_scaffold_add_existing_label
339
+ if controller.respond_to?(:record_select_config)
340
+ record_select_config.model.model_name.human
341
+ else
342
+ active_scaffold_config.model.model_name.human
343
+ end
344
+ end
345
+ end
346
+ end
347
+ end
@@ -0,0 +1,59 @@
1
+ module ActiveScaffold
2
+ module Helpers
3
+ # Helpers that assist with rendering of a human readable search statement
4
+ module HumanConditionHelpers
5
+
6
+ def active_scaffold_human_condition_for(column)
7
+ value = field_search_params[column.name]
8
+ search_ui = column.search_ui
9
+ search_ui ||= column.column.type if column.column
10
+ if override_human_condition_column?(column)
11
+ send(override_human_condition_column(column), value, {})
12
+ elsif search_ui and override_human_condition?(column.search_ui)
13
+ send(override_human_condition(column.search_ui), column, value)
14
+ else
15
+ case search_ui
16
+ when :integer, :decimal, :float
17
+ "#{column.active_record_class.human_attribute_name(column.name)} #{as_(value[:opt].downcase).downcase} #{format_number_value(controller.class.condition_value_for_numeric(column, value[:from]), column.options)} #{value[:opt] == 'BETWEEN' ? '- ' + format_number_value(controller.class.condition_value_for_numeric(column, value[:to]), column.options).to_s : ''}"
18
+ when :string
19
+ opt = ActiveScaffold::Finder::StringComparators.index(value[:opt]) || value[:opt]
20
+ "#{column.active_record_class.human_attribute_name(column.name)} #{as_(opt).downcase} '#{value[:from]}' #{opt == 'BETWEEN' ? '- ' + value[:to].to_s : ''}"
21
+ when :date, :time, :datetime, :timestamp
22
+ conversion = column.column.type == :date ? :to_date : :to_time
23
+ from = controller.condition_value_for_datetime(value[:from], conversion)
24
+ to = controller.condition_value_for_datetime(value[:to], conversion)
25
+ "#{column.active_record_class.human_attribute_name(column.name)} #{as_(value[:opt])} #{I18n.l(from)} #{value[:opt] == 'BETWEEN' ? '- ' + I18n.l(to) : ''}"
26
+ when :select, :multi_select, :record_select
27
+ associated = value
28
+ associated = [associated].compact unless associated.is_a? Array
29
+ associated = column.association.klass.find(associated.map(&:to_i)).collect(&:to_label) if column.association
30
+ "#{column.active_record_class.human_attribute_name(column.name)} = #{associated.join(', ')}"
31
+ when :boolean, :checkbox
32
+ label = column.column.type_cast(value) ? as_(:true) : as_(:false)
33
+ "#{column.active_record_class.human_attribute_name(column.name)} = #{label}"
34
+ when :null
35
+ "#{column.active_record_class.human_attribute_name(column.name)} #{as_(value.to_sym)}"
36
+ end
37
+ end unless value.nil?
38
+ end
39
+
40
+ def override_human_condition_column?(column)
41
+ respond_to?(override_human_condition_column(column))
42
+ end
43
+
44
+ # the naming convention for overriding form fields with helpers
45
+ def override_human_condition_column(column)
46
+ "#{column.name}_human_condition_column"
47
+ end
48
+
49
+ def override_human_condition?(search_ui)
50
+ respond_to?(override_human_condition(search_ui))
51
+ end
52
+
53
+ # the naming convention for overriding human condition search_ui types
54
+ def override_human_condition(search_ui)
55
+ "active_scaffold_human_condition_#{search_ui}"
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,127 @@
1
+ module ActiveScaffold
2
+ module Helpers
3
+ # A bunch of helper methods to produce the common view ids
4
+ module IdHelpers
5
+ def id_from_controller(controller)
6
+ controller.to_s.gsub("/", "__")
7
+ end
8
+
9
+ def controller_id
10
+ controller_id ||= 'as_' + id_from_controller(params[:eid] || params[:parent_controller] || params[:controller])
11
+ end
12
+
13
+ def active_scaffold_id
14
+ "#{controller_id}-active-scaffold"
15
+ end
16
+
17
+ def active_scaffold_content_id
18
+ "#{controller_id}-content"
19
+ end
20
+
21
+ def active_scaffold_tbody_id
22
+ "#{controller_id}-tbody"
23
+ end
24
+
25
+ def active_scaffold_messages_id
26
+ "#{controller_id}-messages"
27
+ end
28
+
29
+ def active_scaffold_calculations_id(column = nil)
30
+ "#{controller_id}-calculations#{'-' + column.name.to_s if column}"
31
+ end
32
+
33
+ def empty_message_id
34
+ "#{controller_id}-empty-message"
35
+ end
36
+
37
+ def before_header_id
38
+ "#{controller_id}-search-container"
39
+ end
40
+
41
+ def search_input_id
42
+ "#{controller_id}-search-input"
43
+ end
44
+
45
+ def table_action_id(name)
46
+ "#{controller_id}-action-table-#{name}"
47
+ end
48
+
49
+ def action_link_id(link_action,link_id)
50
+ "#{controller_id}-#{link_action}-#{link_id}-link"
51
+ end
52
+
53
+ def active_scaffold_column_header_id(column)
54
+ name = column.respond_to?(:name) ? column.name : column.to_s
55
+ clean_id "#{controller_id}-#{name}-column"
56
+ end
57
+
58
+ def element_row_id(options = {})
59
+ options[:action] ||= params[:action]
60
+ options[:id] ||= params[:id]
61
+ options[:id] ||= params[:parent_id]
62
+ clean_id "#{controller_id}-#{options[:action]}-#{options[:id]}-row"
63
+ end
64
+
65
+ def element_cell_id(options = {})
66
+ options[:action] ||= params[:action]
67
+ options[:id] ||= params[:id]
68
+ options[:id] ||= params[:parent_id]
69
+ options[:name] ||= params[:name]
70
+ clean_id "#{controller_id}-#{options[:action]}-#{options[:id]}-#{options[:name]}-cell"
71
+ end
72
+
73
+ def element_form_id(options = {})
74
+ options[:action] ||= params[:action]
75
+ options[:id] ||= params[:id]
76
+ options[:id] ||= params[:parent_id]
77
+ clean_id "#{controller_id}-#{options[:action]}-#{options[:id]}-form"
78
+ end
79
+
80
+ def association_subform_id(column)
81
+ klass = column.association.klass.to_s.underscore
82
+ clean_id "#{controller_id}-associated-#{klass}"
83
+ end
84
+
85
+ def loading_indicator_id(options = {})
86
+ options[:action] ||= params[:action]
87
+ clean_id "#{controller_id}-#{options[:action]}-#{options[:id]}-loading-indicator"
88
+ end
89
+
90
+ def sub_section_id(options = {})
91
+ options[:id] ||= params[:id]
92
+ options[:id] ||= params[:parent_id]
93
+ clean_id "#{controller_id}-#{options[:id]}-#{options[:sub_section]}-subsection"
94
+ end
95
+
96
+ def sub_form_id(options = {})
97
+ options[:id] ||= params[:id]
98
+ options[:id] ||= params[:parent_id]
99
+ clean_id "#{controller_id}-#{options[:id]}-#{options[:association]}-subform"
100
+ end
101
+
102
+ def sub_form_list_id(options = {})
103
+ options[:id] ||= params[:id]
104
+ options[:id] ||= params[:parent_id]
105
+ clean_id "#{controller_id}-#{options[:id]}-#{options[:association]}-subform-list"
106
+ end
107
+
108
+ def element_messages_id(options = {})
109
+ options[:action] ||= params[:action]
110
+ options[:id] ||= params[:id]
111
+ options[:id] ||= params[:parent_id]
112
+ clean_id "#{controller_id}-#{options[:action]}-#{options[:id]}-messages"
113
+ end
114
+
115
+ def action_iframe_id(options)
116
+ "#{controller_id}-#{options[:action]}-#{options[:id]}-iframe"
117
+ end
118
+
119
+ private
120
+
121
+ # whitelists id-safe characters
122
+ def clean_id(val)
123
+ val.gsub /[^-_0-9a-zA-Z]/, '-'
124
+ end
125
+ end
126
+ end
127
+ end