active_scaffold_san 3.0.18

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 (284) 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 +69 -0
  8. data/Rakefile +53 -0
  9. data/active_scaffold_vho.gemspec +388 -0
  10. data/frontends/default/images/add.gif +0 -0
  11. data/frontends/default/images/arrow_down.gif +0 -0
  12. data/frontends/default/images/arrow_up.gif +0 -0
  13. data/frontends/default/images/close.gif +0 -0
  14. data/frontends/default/images/config.png +0 -0
  15. data/frontends/default/images/cross.png +0 -0
  16. data/frontends/default/images/gears.png +0 -0
  17. data/frontends/default/images/indicator-small.gif +0 -0
  18. data/frontends/default/images/indicator.gif +0 -0
  19. data/frontends/default/images/magnifier.png +0 -0
  20. data/frontends/default/javascripts/jquery/active_scaffold.js +1004 -0
  21. data/frontends/default/javascripts/jquery/jquery.editinplace.js +743 -0
  22. data/frontends/default/javascripts/prototype/active_scaffold.js +1003 -0
  23. data/frontends/default/javascripts/prototype/dhtml_history.js +867 -0
  24. data/frontends/default/javascripts/prototype/form_enhancements.js +117 -0
  25. data/frontends/default/javascripts/prototype/rico_corner.js +370 -0
  26. data/frontends/default/stylesheets/stylesheet-ie.css +35 -0
  27. data/frontends/default/stylesheets/stylesheet.css +973 -0
  28. data/frontends/default/views/_action_group.html.erb +20 -0
  29. data/frontends/default/views/_add_existing_form.html.erb +30 -0
  30. data/frontends/default/views/_base_form.html.erb +51 -0
  31. data/frontends/default/views/_create_form.html.erb +8 -0
  32. data/frontends/default/views/_create_form_on_list.html.erb +6 -0
  33. data/frontends/default/views/_field_search.html.erb +32 -0
  34. data/frontends/default/views/_form.html.erb +24 -0
  35. data/frontends/default/views/_form_association.html.erb +19 -0
  36. data/frontends/default/views/_form_association_footer.html.erb +40 -0
  37. data/frontends/default/views/_form_attribute.html.erb +15 -0
  38. data/frontends/default/views/_form_hidden_attribute.html.erb +2 -0
  39. data/frontends/default/views/_form_messages.html.erb +5 -0
  40. data/frontends/default/views/_horizontal_subform.html.erb +29 -0
  41. data/frontends/default/views/_horizontal_subform_header.html.erb +10 -0
  42. data/frontends/default/views/_horizontal_subform_record.html.erb +37 -0
  43. data/frontends/default/views/_human_conditions.html.erb +1 -0
  44. data/frontends/default/views/_list.html.erb +18 -0
  45. data/frontends/default/views/_list_actions.html.erb +15 -0
  46. data/frontends/default/views/_list_calculations.html.erb +16 -0
  47. data/frontends/default/views/_list_column_headings.html.erb +12 -0
  48. data/frontends/default/views/_list_header.html.erb +10 -0
  49. data/frontends/default/views/_list_inline_adapter.html.erb +10 -0
  50. data/frontends/default/views/_list_messages.html.erb +32 -0
  51. data/frontends/default/views/_list_pagination.html.erb +11 -0
  52. data/frontends/default/views/_list_pagination_links.html.erb +9 -0
  53. data/frontends/default/views/_list_record.html.erb +14 -0
  54. data/frontends/default/views/_list_record_columns.html.erb +8 -0
  55. data/frontends/default/views/_list_with_header.html.erb +32 -0
  56. data/frontends/default/views/_messages.html.erb +10 -0
  57. data/frontends/default/views/_render_field.js.rjs +10 -0
  58. data/frontends/default/views/_row.html.erb +12 -0
  59. data/frontends/default/views/_search.html.erb +34 -0
  60. data/frontends/default/views/_search_attribute.html.erb +10 -0
  61. data/frontends/default/views/_show.html.erb +8 -0
  62. data/frontends/default/views/_show_columns.html.erb +15 -0
  63. data/frontends/default/views/_update_actions.html.erb +9 -0
  64. data/frontends/default/views/_update_form.html.erb +6 -0
  65. data/frontends/default/views/_vertical_subform.html.erb +12 -0
  66. data/frontends/default/views/_vertical_subform_record.html.erb +38 -0
  67. data/frontends/default/views/action_confirmation.html.erb +13 -0
  68. data/frontends/default/views/add_existing.js.rjs +17 -0
  69. data/frontends/default/views/add_existing_form.html.erb +5 -0
  70. data/frontends/default/views/create.html.erb +5 -0
  71. data/frontends/default/views/delete.html.erb +13 -0
  72. data/frontends/default/views/destroy.js.rjs +23 -0
  73. data/frontends/default/views/edit_associated.js.rjs +11 -0
  74. data/frontends/default/views/field_search.html.erb +5 -0
  75. data/frontends/default/views/form_messages.js.rjs +1 -0
  76. data/frontends/default/views/list.html.erb +1 -0
  77. data/frontends/default/views/list.js.rjs +1 -0
  78. data/frontends/default/views/on_action_update.js.rjs +8 -0
  79. data/frontends/default/views/on_create.js.rjs +41 -0
  80. data/frontends/default/views/on_mark_all.js.rjs +4 -0
  81. data/frontends/default/views/on_update.js.rjs +28 -0
  82. data/frontends/default/views/search.html.erb +5 -0
  83. data/frontends/default/views/show.html.erb +5 -0
  84. data/frontends/default/views/update.html.erb +8 -0
  85. data/frontends/default/views/update_column.js.rjs +13 -0
  86. data/frontends/default/views/update_row.js.rjs +1 -0
  87. data/init.rb +8 -0
  88. data/lib/active_scaffold.rb +360 -0
  89. data/lib/active_scaffold/actions/common_search.rb +22 -0
  90. data/lib/active_scaffold/actions/core.rb +180 -0
  91. data/lib/active_scaffold/actions/create.rb +149 -0
  92. data/lib/active_scaffold/actions/delete.rb +75 -0
  93. data/lib/active_scaffold/actions/field_search.rb +82 -0
  94. data/lib/active_scaffold/actions/list.rb +184 -0
  95. data/lib/active_scaffold/actions/mark.rb +63 -0
  96. data/lib/active_scaffold/actions/nested.rb +250 -0
  97. data/lib/active_scaffold/actions/search.rb +47 -0
  98. data/lib/active_scaffold/actions/show.rb +61 -0
  99. data/lib/active_scaffold/actions/subform.rb +27 -0
  100. data/lib/active_scaffold/actions/update.rb +151 -0
  101. data/lib/active_scaffold/active_record_permissions.rb +134 -0
  102. data/lib/active_scaffold/attribute_params.rb +211 -0
  103. data/lib/active_scaffold/bridges/ancestry/bridge.rb +5 -0
  104. data/lib/active_scaffold/bridges/ancestry/lib/ancestry_bridge.rb +39 -0
  105. data/lib/active_scaffold/bridges/bridge.rb +59 -0
  106. data/lib/active_scaffold/bridges/calendar_date_select/bridge.rb +16 -0
  107. data/lib/active_scaffold/bridges/calendar_date_select/lib/as_cds_bridge.rb +83 -0
  108. data/lib/active_scaffold/bridges/cancan/bridge.rb +12 -0
  109. data/lib/active_scaffold/bridges/cancan/lib/cancan_bridge.rb +107 -0
  110. data/lib/active_scaffold/bridges/carrierwave/bridge.rb +9 -0
  111. data/lib/active_scaffold/bridges/carrierwave/lib/carrierwave_bridge.rb +33 -0
  112. data/lib/active_scaffold/bridges/carrierwave/lib/carrierwave_bridge_helpers.rb +12 -0
  113. data/lib/active_scaffold/bridges/carrierwave/lib/form_ui.rb +45 -0
  114. data/lib/active_scaffold/bridges/carrierwave/lib/list_ui.rb +17 -0
  115. data/lib/active_scaffold/bridges/date_picker/bridge.rb +24 -0
  116. data/lib/active_scaffold/bridges/date_picker/lib/datepicker_bridge.rb +225 -0
  117. data/lib/active_scaffold/bridges/date_picker/public/javascripts/date_picker_bridge.js +22 -0
  118. data/lib/active_scaffold/bridges/file_column/bridge.rb +11 -0
  119. data/lib/active_scaffold/bridges/file_column/lib/as_file_column_bridge.rb +46 -0
  120. data/lib/active_scaffold/bridges/file_column/lib/file_column_helpers.rb +59 -0
  121. data/lib/active_scaffold/bridges/file_column/lib/form_ui.rb +37 -0
  122. data/lib/active_scaffold/bridges/file_column/lib/list_ui.rb +26 -0
  123. data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +43 -0
  124. data/lib/active_scaffold/bridges/file_column/test/mock_model.rb +9 -0
  125. data/lib/active_scaffold/bridges/file_column/test/test_helper.rb +15 -0
  126. data/lib/active_scaffold/bridges/paperclip/bridge.rb +12 -0
  127. data/lib/active_scaffold/bridges/paperclip/lib/form_ui.rb +27 -0
  128. data/lib/active_scaffold/bridges/paperclip/lib/list_ui.rb +16 -0
  129. data/lib/active_scaffold/bridges/paperclip/lib/paperclip_bridge.rb +38 -0
  130. data/lib/active_scaffold/bridges/paperclip/lib/paperclip_bridge_helpers.rb +26 -0
  131. data/lib/active_scaffold/bridges/semantic_attributes/bridge.rb +5 -0
  132. data/lib/active_scaffold/bridges/semantic_attributes/lib/semantic_attributes_bridge.rb +20 -0
  133. data/lib/active_scaffold/bridges/shared/date_bridge.rb +209 -0
  134. data/lib/active_scaffold/bridges/tiny_mce/bridge.rb +5 -0
  135. data/lib/active_scaffold/bridges/tiny_mce/lib/tiny_mce_bridge.rb +61 -0
  136. data/lib/active_scaffold/bridges/validation_reflection/bridge.rb +8 -0
  137. data/lib/active_scaffold/bridges/validation_reflection/lib/validation_reflection_bridge.rb +21 -0
  138. data/lib/active_scaffold/config/base.rb +62 -0
  139. data/lib/active_scaffold/config/core.rb +220 -0
  140. data/lib/active_scaffold/config/create.rb +51 -0
  141. data/lib/active_scaffold/config/delete.rb +34 -0
  142. data/lib/active_scaffold/config/field_search.rb +75 -0
  143. data/lib/active_scaffold/config/form.rb +47 -0
  144. data/lib/active_scaffold/config/list.rb +174 -0
  145. data/lib/active_scaffold/config/mark.rb +22 -0
  146. data/lib/active_scaffold/config/nested.rb +44 -0
  147. data/lib/active_scaffold/config/search.rb +69 -0
  148. data/lib/active_scaffold/config/show.rb +35 -0
  149. data/lib/active_scaffold/config/subform.rb +35 -0
  150. data/lib/active_scaffold/config/update.rb +46 -0
  151. data/lib/active_scaffold/configurable.rb +29 -0
  152. data/lib/active_scaffold/constraints.rb +184 -0
  153. data/lib/active_scaffold/data_structures/action_columns.rb +137 -0
  154. data/lib/active_scaffold/data_structures/action_link.rb +175 -0
  155. data/lib/active_scaffold/data_structures/action_links.rb +185 -0
  156. data/lib/active_scaffold/data_structures/actions.rb +45 -0
  157. data/lib/active_scaffold/data_structures/column.rb +355 -0
  158. data/lib/active_scaffold/data_structures/columns.rb +75 -0
  159. data/lib/active_scaffold/data_structures/error_message.rb +24 -0
  160. data/lib/active_scaffold/data_structures/nested_info.rb +123 -0
  161. data/lib/active_scaffold/data_structures/set.rb +62 -0
  162. data/lib/active_scaffold/data_structures/sorting.rb +168 -0
  163. data/lib/active_scaffold/extensions/action_controller_rendering.rb +20 -0
  164. data/lib/active_scaffold/extensions/action_view_rendering.rb +123 -0
  165. data/lib/active_scaffold/extensions/action_view_resolver.rb +7 -0
  166. data/lib/active_scaffold/extensions/active_association_reflection.rb +13 -0
  167. data/lib/active_scaffold/extensions/active_record_offset.rb +12 -0
  168. data/lib/active_scaffold/extensions/array.rb +7 -0
  169. data/lib/active_scaffold/extensions/localize.rb +10 -0
  170. data/lib/active_scaffold/extensions/name_option_for_datetime.rb +12 -0
  171. data/lib/active_scaffold/extensions/nil_id_in_url_params.rb +7 -0
  172. data/lib/active_scaffold/extensions/paginator_extensions.rb +26 -0
  173. data/lib/active_scaffold/extensions/reverse_associations.rb +62 -0
  174. data/lib/active_scaffold/extensions/routing_mapper.rb +34 -0
  175. data/lib/active_scaffold/extensions/to_label.rb +8 -0
  176. data/lib/active_scaffold/extensions/unsaved_associated.rb +61 -0
  177. data/lib/active_scaffold/extensions/unsaved_record.rb +20 -0
  178. data/lib/active_scaffold/extensions/usa_state.rb +46 -0
  179. data/lib/active_scaffold/finder.rb +343 -0
  180. data/lib/active_scaffold/helpers/association_helpers.rb +40 -0
  181. data/lib/active_scaffold/helpers/controller_helpers.rb +87 -0
  182. data/lib/active_scaffold/helpers/country_helpers.rb +352 -0
  183. data/lib/active_scaffold/helpers/form_column_helpers.rb +350 -0
  184. data/lib/active_scaffold/helpers/human_condition_helpers.rb +59 -0
  185. data/lib/active_scaffold/helpers/id_helpers.rb +127 -0
  186. data/lib/active_scaffold/helpers/list_column_helpers.rb +361 -0
  187. data/lib/active_scaffold/helpers/pagination_helpers.rb +55 -0
  188. data/lib/active_scaffold/helpers/search_column_helpers.rb +249 -0
  189. data/lib/active_scaffold/helpers/show_column_helpers.rb +46 -0
  190. data/lib/active_scaffold/helpers/view_helpers.rb +360 -0
  191. data/lib/active_scaffold/locale/de.rb +120 -0
  192. data/lib/active_scaffold/locale/en.rb +119 -0
  193. data/lib/active_scaffold/locale/es.yml +115 -0
  194. data/lib/active_scaffold/locale/fr.rb +122 -0
  195. data/lib/active_scaffold/locale/hu.yml +63 -0
  196. data/lib/active_scaffold/locale/ja.yml +64 -0
  197. data/lib/active_scaffold/locale/ru.yml +119 -0
  198. data/lib/active_scaffold/marked_model.rb +38 -0
  199. data/lib/active_scaffold/paginator.rb +136 -0
  200. data/lib/active_scaffold/responds_to_parent.rb +70 -0
  201. data/lib/active_scaffold/version.rb +9 -0
  202. data/lib/active_scaffold_assets.rb +45 -0
  203. data/lib/active_scaffold_env.rb +14 -0
  204. data/lib/active_scaffold_vho.rb +2 -0
  205. data/lib/generators/active_scaffold/USAGE +29 -0
  206. data/lib/generators/active_scaffold/active_scaffold_generator.rb +20 -0
  207. data/lib/generators/active_scaffold_controller/USAGE +19 -0
  208. data/lib/generators/active_scaffold_controller/active_scaffold_controller_generator.rb +29 -0
  209. data/lib/generators/active_scaffold_controller/templates/controller.rb +4 -0
  210. data/lib/generators/active_scaffold_controller/templates/helper.rb +2 -0
  211. data/lib/generators/active_scaffold_setup/USAGE +10 -0
  212. data/lib/generators/active_scaffold_setup/active_scaffold_setup_generator.rb +61 -0
  213. data/public/blank.html +33 -0
  214. data/shoulda_macros/macros.rb +136 -0
  215. data/test/bridges/bridge_test.rb +47 -0
  216. data/test/config/base_test.rb +15 -0
  217. data/test/config/create_test.rb +55 -0
  218. data/test/config/list_test.rb +74 -0
  219. data/test/config/show_test.rb +43 -0
  220. data/test/config/update_test.rb +17 -0
  221. data/test/const_mocker.rb +36 -0
  222. data/test/data_structures/action_columns_test.rb +113 -0
  223. data/test/data_structures/action_link_test.rb +78 -0
  224. data/test/data_structures/action_links_test.rb +78 -0
  225. data/test/data_structures/actions_test.rb +25 -0
  226. data/test/data_structures/association_column_test.rb +42 -0
  227. data/test/data_structures/column_test.rb +185 -0
  228. data/test/data_structures/columns_test.rb +69 -0
  229. data/test/data_structures/error_message_test.rb +28 -0
  230. data/test/data_structures/set_test.rb +86 -0
  231. data/test/data_structures/sorting_test.rb +126 -0
  232. data/test/data_structures/standard_column_test.rb +24 -0
  233. data/test/data_structures/virtual_column_test.rb +23 -0
  234. data/test/extensions/active_record_test.rb +45 -0
  235. data/test/extensions/array_test.rb +12 -0
  236. data/test/helpers/form_column_helpers_test.rb +31 -0
  237. data/test/helpers/list_column_helpers_test.rb +31 -0
  238. data/test/helpers/pagination_helpers_test.rb +55 -0
  239. data/test/misc/active_record_permissions_test.rb +154 -0
  240. data/test/misc/attribute_params_test.rb +110 -0
  241. data/test/misc/configurable_test.rb +96 -0
  242. data/test/misc/constraints_test.rb +193 -0
  243. data/test/misc/finder_test.rb +93 -0
  244. data/test/misc/lang_test.rb +12 -0
  245. data/test/mock_app/.gitignore +2 -0
  246. data/test/mock_app/app/controllers/application_controller.rb +10 -0
  247. data/test/mock_app/app/helpers/application_helper.rb +3 -0
  248. data/test/mock_app/config/boot.rb +110 -0
  249. data/test/mock_app/config/database.yml +16 -0
  250. data/test/mock_app/config/environment.rb +43 -0
  251. data/test/mock_app/config/environments/development.rb +17 -0
  252. data/test/mock_app/config/environments/production.rb +28 -0
  253. data/test/mock_app/config/environments/test.rb +28 -0
  254. data/test/mock_app/config/initializers/backtrace_silencers.rb +7 -0
  255. data/test/mock_app/config/initializers/inflections.rb +10 -0
  256. data/test/mock_app/config/initializers/mime_types.rb +5 -0
  257. data/test/mock_app/config/initializers/new_rails_defaults.rb +19 -0
  258. data/test/mock_app/config/initializers/session_store.rb +15 -0
  259. data/test/mock_app/config/locales/en.yml +5 -0
  260. data/test/mock_app/config/routes.rb +43 -0
  261. data/test/mock_app/db/test.sqlite3 +1 -0
  262. data/test/mock_app/public/blank.html +33 -0
  263. data/test/mock_app/public/images/active_scaffold/DO_NOT_EDIT +2 -0
  264. data/test/mock_app/public/images/active_scaffold/default/add.gif +0 -0
  265. data/test/mock_app/public/images/active_scaffold/default/arrow_down.gif +0 -0
  266. data/test/mock_app/public/images/active_scaffold/default/arrow_up.gif +0 -0
  267. data/test/mock_app/public/images/active_scaffold/default/close.gif +0 -0
  268. data/test/mock_app/public/images/active_scaffold/default/cross.png +0 -0
  269. data/test/mock_app/public/images/active_scaffold/default/indicator-small.gif +0 -0
  270. data/test/mock_app/public/images/active_scaffold/default/indicator.gif +0 -0
  271. data/test/mock_app/public/images/active_scaffold/default/magnifier.png +0 -0
  272. data/test/mock_app/public/javascripts/active_scaffold/DO_NOT_EDIT +2 -0
  273. data/test/mock_app/public/javascripts/active_scaffold/default/active_scaffold.js +532 -0
  274. data/test/mock_app/public/javascripts/active_scaffold/default/dhtml_history.js +867 -0
  275. data/test/mock_app/public/javascripts/active_scaffold/default/form_enhancements.js +117 -0
  276. data/test/mock_app/public/javascripts/active_scaffold/default/rico_corner.js +370 -0
  277. data/test/mock_app/public/stylesheets/active_scaffold/DO_NOT_EDIT +2 -0
  278. data/test/mock_app/public/stylesheets/active_scaffold/default/stylesheet-ie.css +35 -0
  279. data/test/mock_app/public/stylesheets/active_scaffold/default/stylesheet.css +842 -0
  280. data/test/model_stub.rb +55 -0
  281. data/test/run_all.rb +8 -0
  282. data/test/test_helper.rb +39 -0
  283. data/uninstall.rb +13 -0
  284. metadata +497 -0
@@ -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(controller = (params[:eid] || params[:parent_controller] || params[:controller]))
10
+ controller_id ||= 'as_' + id_from_controller(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(options = {})
26
+ "#{options[:controller_id] || 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 "#{options[:controller_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
@@ -0,0 +1,361 @@
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, :link => text)
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)
42
+ return text if link.crud_type.nil?
43
+ url_options[:link] = as_(:create_new) if link.crud_type == :create
44
+ end
45
+
46
+ if column_link_authorized?(link, column, record, associated)
47
+ render_action_link(link, url_options, record)
48
+ else
49
+ "<a class='disabled'>#{text}</a>".html_safe
50
+ end
51
+ else
52
+ text = active_scaffold_inplace_edit(record, column, {:formatted_column => text}) if inplace_edit?(record, column)
53
+ text
54
+ end
55
+ end
56
+
57
+ # setup the action link to inline form
58
+ def action_link_to_inline_form(column, record, associated)
59
+ link = column.link.clone
60
+ if column.polymorphic_association?
61
+ polymorphic_controller = controller_path_for_activerecord(record.send(column.association.name).class)
62
+ return link if polymorphic_controller.nil?
63
+ link.controller = polymorphic_controller
64
+ end
65
+ configure_column_link(link, associated, column.actions_for_association_links)
66
+ end
67
+
68
+ def configure_column_link(link, associated, actions)
69
+ if column_empty?(associated) # if association is empty, we only can link to create form
70
+ if actions.include?(:new)
71
+ link.action = 'new'
72
+ link.crud_type = :create
73
+ end
74
+ elsif actions.include?(:edit)
75
+ link.action = 'edit'
76
+ link.crud_type = :update
77
+ elsif actions.include?(:show)
78
+ link.action = 'show'
79
+ link.crud_type = :read
80
+ elsif actions.include?(:list)
81
+ link.action = 'index'
82
+ link.crud_type = :read
83
+ end
84
+ link
85
+ end
86
+
87
+ def column_link_authorized?(link, column, record, associated)
88
+ if column.association
89
+ associated_for_authorized = if associated.nil? || (associated.respond_to?(:empty?) && associated.empty?)
90
+ column.association.klass
91
+ elsif [:has_many, :has_and_belongs_to_many].include? column.association.macro
92
+ associated.first
93
+ else
94
+ associated
95
+ end
96
+ authorized = associated_for_authorized.authorized_for?(:crud_type => link.crud_type)
97
+ authorized = authorized and record.authorized_for?(:crud_type => :update, :column => column.name) if link.crud_type == :create
98
+ authorized
99
+ else
100
+ record.authorized_for?(:crud_type => link.crud_type)
101
+ end
102
+ end
103
+
104
+ # There are two basic ways to clean a column's value: h() and sanitize(). The latter is useful
105
+ # when the column contains *valid* html data, and you want to just disable any scripting. People
106
+ # can always use field overrides to clean data one way or the other, but having this override
107
+ # lets people decide which way it should happen by default.
108
+ #
109
+ # Why is it not a configuration option? Because it seems like a somewhat rare request. But it
110
+ # could eventually be an option in config.list (and config.show, I guess).
111
+ def clean_column_value(v)
112
+ h(v)
113
+ end
114
+
115
+ ##
116
+ ## Overrides
117
+ ##
118
+ def active_scaffold_column_text(column, record)
119
+ truncate(clean_column_value(record.send(column.name)), :length => column.options[:truncate] || 50)
120
+ end
121
+
122
+ def active_scaffold_column_select(column, record)
123
+ if column.association
124
+ format_column_value(record, column)
125
+ else
126
+ value = record.send(column.name)
127
+ text, val = column.options[:options].find {|text, val| (val || text).to_s == value}
128
+ value = active_scaffold_translated_option(column, text, val).first if text
129
+ format_column_value(record, column, value)
130
+ end
131
+ end
132
+
133
+ def active_scaffold_column_checkbox(column, record)
134
+ options = {:disabled => true, :id => nil, :object => record}
135
+ options.delete(:disabled) if inplace_edit?(record, column)
136
+ check_box(:record, column.name, options)
137
+ end
138
+
139
+ def column_override(column)
140
+ "#{column.name.to_s.gsub('?', '')}_column" # parse out any question marks (see issue 227)
141
+ end
142
+
143
+ def column_override?(column)
144
+ respond_to?(column_override(column))
145
+ end
146
+
147
+ def override_column_ui?(list_ui)
148
+ respond_to?(override_column_ui(list_ui))
149
+ end
150
+
151
+ # the naming convention for overriding column types with helpers
152
+ def override_column_ui(list_ui)
153
+ "active_scaffold_column_#{list_ui}"
154
+ end
155
+
156
+ ##
157
+ ## Formatting
158
+ ##
159
+ def format_column_value(record, column, value = nil)
160
+ value ||= record.send(column.name) unless record.nil?
161
+ if value && column.association # cache association size before calling column_empty?
162
+ associated_size = value.size if column.plural_association? and column.associated_number? # get count before cache association
163
+ cache_association(value, column)
164
+ end
165
+ if column.association.nil? or column_empty?(value)
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
+ send("number_with_#{value.is_a?(Integer) ? 'delimiter' : 'precision'}", 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| v.to_label }
203
+ else
204
+ firsts = value.first(column.associated_limit)
205
+ firsts.collect! { |v| 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(', '))
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
+ all_marked = (marked_records.length >= @page.pager.count)
317
+ tag_options = {:id => "#{controller_id}_mark_heading", :class => "mark_heading in_place_editor_field"}
318
+ tag_options['data-ie_url'] = url_for({:controller => params_for[:controller], :action => 'mark_all', :eid => params[:eid]})
319
+ content_tag(:span, check_box_tag("#{controller_id}_mark_heading_span_input", !all_marked, all_marked), tag_options)
320
+ end
321
+
322
+ def render_column_heading(column, sorting, sort_direction)
323
+ tag_options = {:id => active_scaffold_column_header_id(column), :class => column_heading_class(column, sorting), :title => column.description}
324
+ tag_options.merge!(inplace_edit_tag_attributes(column)) if column.inplace_edit
325
+ content_tag(:th, column_heading_value(column, sorting, sort_direction) + inplace_edit_control(column), tag_options)
326
+ end
327
+
328
+
329
+ def column_heading_value(column, sorting, sort_direction)
330
+ if column.sortable?
331
+ options = {:id => nil, :class => "as_sort",
332
+ 'data-page-history' => controller_id,
333
+ :remote => true, :method => :get}
334
+ url_options = params_for(:action => :index, :page => 1,
335
+ :sort => column.name, :sort_direction => sort_direction)
336
+ link_to column.label, url_options, options
337
+ else
338
+ if column.name != :marked
339
+ content_tag(:p, column.label)
340
+ else
341
+ mark_column_heading
342
+ end
343
+ end
344
+ end
345
+
346
+ def render_nested_view(action_links, url_options, record)
347
+ rendered = []
348
+ action_links.member.each do |link|
349
+ 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)
350
+ link_url_options = {:adapter => '_list_inline_adapter', :format => :js}.merge(action_link_url_options(link, url_options, record, options = {:reuse_eid => true}))
351
+ link_id = get_action_link_id(link_url_options, record, link.column)
352
+ rendered << (controller.send(:render_component_into_view, link_url_options) + javascript_tag("ActiveScaffold.ActionLink.get('#{link_id}').set_opened();"))
353
+ end
354
+ end
355
+ rendered.join(' ').html_safe
356
+ end
357
+
358
+ end
359
+ end
360
+ end
361
+