zena 0.15.2 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (284) hide show
  1. data/.gitignore +20 -0
  2. data/CREDITS +27 -0
  3. data/Capfile +3 -0
  4. data/DEVELOPERS +46 -0
  5. data/History.txt +15 -0
  6. data/MIT-LICENSE +19 -0
  7. data/Rakefile +44 -0
  8. data/TODO +24 -0
  9. data/TODO_ZENA_1_0 +23 -0
  10. data/app/controllers/application_controller.rb +3 -0
  11. data/app/controllers/documents_controller.rb +22 -56
  12. data/app/controllers/nodes_controller.rb +42 -27
  13. data/app/controllers/pings_controller.rb +19 -0
  14. data/app/controllers/relations_controller.rb +5 -1
  15. data/app/controllers/sites_controller.rb +1 -46
  16. data/app/controllers/user_sessions_controller.rb +47 -0
  17. data/app/controllers/users_controller.rb +1 -0
  18. data/app/controllers/versions_controller.rb +25 -7
  19. data/app/controllers/virtual_classes_controller.rb +1 -1
  20. data/app/helpers/application_helper.rb +1 -1
  21. data/app/models/comment.rb +2 -1
  22. data/app/models/contact_content.rb +2 -2
  23. data/app/models/data_entry.rb +5 -6
  24. data/app/models/document.rb +14 -10
  25. data/app/models/document_content.rb +4 -6
  26. data/app/models/iformat.rb +2 -2
  27. data/app/models/image_content.rb +6 -9
  28. data/app/models/node.rb +106 -164
  29. data/app/models/page.rb +0 -20
  30. data/app/models/site.rb +42 -12
  31. data/app/models/template.rb +3 -8
  32. data/app/models/template_content.rb +2 -0
  33. data/app/models/text_document.rb +13 -8
  34. data/app/models/user.rb +47 -100
  35. data/app/models/user_session.rb +4 -0
  36. data/app/models/version.rb +1 -1
  37. data/app/views/comments/create.rjs +3 -3
  38. data/app/views/comments/edit.rjs +1 -1
  39. data/app/views/comments/update.rjs +1 -1
  40. data/app/views/nodes/_import_results.rhtml +1 -1
  41. data/app/views/nodes/create.rjs +3 -3
  42. data/app/views/templates/document_create_tabs/_file.rhtml +1 -2
  43. data/app/views/templates/document_create_tabs/_import.rhtml +7 -2
  44. data/app/views/templates/edit_tabs/_document.rhtml +1 -3
  45. data/app/views/templates/edit_tabs/_image.rhtml +1 -3
  46. data/app/views/versions/_tr.rhtml +1 -1
  47. data/app/views/versions/edit.rhtml +2 -26
  48. data/bin/zena +6 -1
  49. data/bricks/delayed_job/README +18 -0
  50. data/bricks/delayed_job/migrate/20091104191643_create_delayed_jobs_table.rb +19 -0
  51. data/bricks/delayed_job/misc/init.rb +8 -0
  52. data/bricks/delayed_job/misc/tasks.rb +2 -0
  53. data/bricks/math/patch/application_helper.rb +1 -1
  54. data/bricks/sphinx/MIT-LICENSE +19 -0
  55. data/bricks/sphinx/README +19 -0
  56. data/bricks/sphinx/lib/use_sphinx.rb +78 -0
  57. data/bricks/sphinx/migrate/20091102171258_add_delta_for_sphinx.rb +9 -0
  58. data/bricks/sphinx/misc/deploy.rb +20 -0
  59. data/bricks/sphinx/misc/sphinx.yml +12 -0
  60. data/bricks/sphinx/misc/tasks.rb +21 -0
  61. data/bricks/sphinx/patch/node.rb +8 -0
  62. data/bricks/tags/lib/has_tags.rb +5 -3
  63. data/bricks/tags/test/zafu/tags.yml +13 -1
  64. data/config/bricks.yml +35 -0
  65. data/config/deploy.rb +8 -1
  66. data/config/environment.rb +1 -1
  67. data/config/environments/production.rb +1 -1
  68. data/config/gems.yml +28 -5
  69. data/config/sphinx.yml +12 -0
  70. data/db/init/base/skins/default/Node-+popupLayout.zafu +1 -16
  71. data/db/migrate/20091026161708_add_persistence_token.rb +13 -0
  72. data/db/migrate/20091101184952_add_session_table.rb +16 -0
  73. data/db/migrate/20091123175137_add_single_access_token.rb +9 -0
  74. data/db/migrate/20091124161608_rebuild_fullpath.rb +11 -0
  75. data/db/schema.rb +21 -8
  76. data/doc/README_FOR_APP +24 -0
  77. data/doc/fixtures.graffle +19568 -0
  78. data/doc/fixtures.pdf +0 -0
  79. data/doc/template/LICENSE +184 -0
  80. data/doc/template/README +37 -0
  81. data/doc/template/allison.css +283 -0
  82. data/doc/template/allison.js +307 -0
  83. data/doc/template/allison.rb +260 -0
  84. data/doc/template/cache/BODY +588 -0
  85. data/doc/template/cache/CLASS_INDEX +4 -0
  86. data/doc/template/cache/CLASS_PAGE +1 -0
  87. data/doc/template/cache/FILE_INDEX +4 -0
  88. data/doc/template/cache/FILE_PAGE +1 -0
  89. data/doc/template/cache/FONTS +1 -0
  90. data/doc/template/cache/FR_INDEX_BODY +1 -0
  91. data/doc/template/cache/IMGPATH +1 -0
  92. data/doc/template/cache/INDEX +1 -0
  93. data/doc/template/cache/JAVASCRIPT +307 -0
  94. data/doc/template/cache/METHOD_INDEX +4 -0
  95. data/doc/template/cache/METHOD_LIST +1 -0
  96. data/doc/template/cache/SRC_PAGE +1 -0
  97. data/doc/template/cache/STYLE +283 -0
  98. data/doc/template/cache/URL +1 -0
  99. data/doc/zafu_changes.yml +29 -0
  100. data/lib/base_additions.rb +1 -1
  101. data/lib/bricks.rb +9 -0
  102. data/lib/bricks/loader.rb +86 -0
  103. data/lib/bricks/requirements_validation.rb +71 -0
  104. data/lib/tasks/zena.rake +42 -4
  105. data/lib/zafu/action.rb +285 -0
  106. data/lib/zafu/ajax.rb +93 -0
  107. data/lib/zafu/attributes.rb +117 -0
  108. data/lib/zafu/calendar.rb +159 -0
  109. data/lib/zafu/context.rb +330 -0
  110. data/lib/zafu/core/html.rb +102 -0
  111. data/lib/zafu/core/move_to_parser.rb +167 -0
  112. data/lib/zafu/dates.rb +58 -0
  113. data/lib/zafu/display.rb +502 -0
  114. data/lib/zafu/eval.rb +66 -0
  115. data/lib/zafu/experimental.rb +66 -0
  116. data/lib/zafu/i18n.rb +64 -0
  117. data/lib/zafu/meta.rb +25 -0
  118. data/lib/zafu/refactor.rb +73 -0
  119. data/lib/zafu/support/context.rb +265 -0
  120. data/lib/zafu/support/dom.rb +145 -0
  121. data/lib/zafu/support/erb.rb +62 -0
  122. data/lib/zafu/support/flow.rb +401 -0
  123. data/lib/zafu/support/forms.rb +461 -0
  124. data/lib/zafu/support/links.rb +306 -0
  125. data/lib/zafu_parser.rb +26 -2
  126. data/lib/zena.rb +34 -15
  127. data/lib/zena/acts/multiversion.rb +2 -2
  128. data/lib/zena/acts/secure.rb +41 -30
  129. data/lib/zena/app.rb +7 -10
  130. data/lib/zena/controller/test_case.rb +12 -7
  131. data/lib/zena/crypto_provider/initial.rb +15 -0
  132. data/lib/zena/db.rb +6 -1
  133. data/lib/zena/deploy.rb +34 -6
  134. data/lib/zena/deploy/logrotate_app.rhtml +9 -0
  135. data/lib/zena/deploy/logrotate_host.rhtml +34 -0
  136. data/lib/zena/deploy/template.rb +1 -9
  137. data/lib/zena/foxy_parser.rb +1 -1
  138. data/lib/zena/info.rb +3 -1
  139. data/lib/zena/migrator.rb +1 -1
  140. data/lib/zena/parser.rb +12 -4
  141. data/lib/zena/parser/zazen_rules.rb +6 -6
  142. data/lib/zena/parser/zena_rules.rb +1 -7
  143. data/lib/zena/routes.rb +5 -5
  144. data/lib/zena/test_controller.rb +7 -2
  145. data/lib/zena/unit/test_case.rb +6 -8
  146. data/lib/zena/use/ajax.rb +10 -10
  147. data/lib/zena/use/authlogic.rb +93 -0
  148. data/lib/zena/use/dyn_attributes.rb +5 -0
  149. data/lib/zena/use/html_tags.rb +16 -34
  150. data/lib/zena/use/i18n.rb +4 -1
  151. data/lib/zena/use/node_query_finders.rb +8 -4
  152. data/lib/zena/use/refactor.rb +8 -20
  153. data/lib/zena/use/relations.rb +1 -0
  154. data/lib/zena/use/rendering.rb +4 -2
  155. data/lib/zena/use/search.rb +52 -0
  156. data/lib/zena/use/test_helper.rb +27 -28
  157. data/lib/zena/use/upload.rb +188 -0
  158. data/lib/zena/use/urls.rb +16 -14
  159. data/lib/zena/use/zafu.rb +16 -63
  160. data/lib/zena/use/zazen.rb +8 -8
  161. data/lib/zena/view/test_case.rb +8 -4
  162. data/locale/en/LC_MESSAGES/zena.mo +0 -0
  163. data/locale/en/zena.po +3 -3
  164. data/public/.htaccess +40 -0
  165. data/public/javascripts/upload-progress.js +17 -8
  166. data/public/javascripts/zena.js +8 -2
  167. data/public/stylesheets/popup.css +1 -0
  168. data/script/about +3 -0
  169. data/script/apache_logging +25 -0
  170. data/script/breakpointer +3 -0
  171. data/script/console +3 -0
  172. data/script/dbconsole +3 -0
  173. data/script/destroy +3 -0
  174. data/script/generate +3 -0
  175. data/script/performance/benchmarker +3 -0
  176. data/script/performance/profiler +3 -0
  177. data/script/plugin +3 -0
  178. data/script/process/inspector +3 -0
  179. data/script/process/reaper +3 -0
  180. data/script/process/spawner +3 -0
  181. data/script/runner +3 -0
  182. data/script/server +3 -0
  183. data/script/set_revision +29 -0
  184. data/spec/controllers/versions_controller_spec.rb +11 -0
  185. data/test/fixtures/files/Node-test.zafu +1 -1
  186. data/test/functional/nodes_controller_test.rb +25 -0
  187. data/test/functional/pings_controller_test.rb +8 -0
  188. data/test/functional/user_sessions_controller_test.rb +59 -0
  189. data/test/functional/users_controller_test.rb +81 -19
  190. data/test/helpers/node_query/filters.yml +5 -0
  191. data/test/helpers/node_query_test.rb +3 -3
  192. data/test/integration/multiple_hosts_test.rb +1 -1
  193. data/test/integration/navigation_test.rb +1 -1
  194. data/test/sites/complex/users.yml +1 -1
  195. data/test/sites/ocean/users.yml +3 -3
  196. data/test/sites/zena/users.yml +5 -4
  197. data/test/test_zena.rb +38 -38
  198. data/test/unit/cached_page_test.rb +2 -2
  199. data/test/unit/comment_test.rb +0 -1
  200. data/test/unit/document_test.rb +23 -11
  201. data/test/unit/helpers/ping_helper_test.rb +4 -0
  202. data/test/unit/multiversion_test.rb +24 -16
  203. data/test/unit/node_test.rb +32 -93
  204. data/test/unit/note_test.rb +9 -0
  205. data/test/unit/page_test.rb +2 -2
  206. data/test/unit/secure_test.rb +2 -12
  207. data/test/unit/site_test.rb +43 -24
  208. data/test/unit/template_test.rb +45 -3
  209. data/test/unit/text_document_test.rb +4 -3
  210. data/test/unit/user_test.rb +13 -33
  211. data/test/unit/zena/db_test.rb +8 -0
  212. data/test/unit/zena/parser/zazen.yml +4 -4
  213. data/test/unit/zena/use/dates_view_methods_test.rb +2 -1
  214. data/test/unit/zena/use/html_tags_test.rb +12 -4
  215. data/test/unit/zena/use/refactor_test.rb +4 -3
  216. data/test/unit/zena/use/rendering_test.rb +1 -0
  217. data/test/unit/zena/use/upload_test.rb +76 -0
  218. data/test/unit/zena/use/urls_test.rb +4 -0
  219. data/test/unit/zena/use/zafu_test.rb +8 -0
  220. data/test/unit/zena/workflow/status_version_test.rb +6 -0
  221. data/test/unit/zena/zena_tags/ajax.yml +4 -4
  222. data/test/unit/zena/zena_tags/basic.yml +21 -10
  223. data/test/unit/zena/zena_tags/relations.yml +0 -6
  224. data/test/unit/zena/zena_tags/rubyless.yml +35 -0
  225. data/test/unit/zena/zena_tags/zazen.yml +4 -4
  226. data/test/unit/zena/zena_tags_test.rb +36 -4
  227. data/vendor/TextMate/Zena.tmbundle/Commands/Run all yaml tests.tmCommand +1 -1
  228. data/vendor/TextMate/Zena.tmbundle/Commands/Run focused yaml test.tmCommand +2 -3
  229. data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/catch_exception.rb +39 -0
  230. data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/run_script.rb +102 -58
  231. data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/stdin_dialog.rb +14 -0
  232. data/vendor/TextMate/Zena.tmbundle/info.plist +2 -0
  233. data/zena.gemspec +2085 -0
  234. metadata +265 -90
  235. data/app/controllers/sessions_controller.rb +0 -41
  236. data/app/views/sites/zena_up.html.erb +0 -11
  237. data/config/database.yml +0 -40
  238. data/db/production.sqlite3 +0 -0
  239. data/lib/bricks/patcher.rb +0 -68
  240. data/lib/zena/parser/zena_tags.rb +0 -3562
  241. data/lib/zena/use/authentification.rb +0 -120
  242. data/public/images/ext/contact_pv.png +0 -0
  243. data/public/images/ext/other_pv.png +0 -0
  244. data/public/images/ext/page_pv.png +0 -0
  245. data/public/images/ext/page_tiny.png +0 -0
  246. data/public/images/ext/pdf_pv.png +0 -0
  247. data/public/images/ext/post_pv.png +0 -0
  248. data/public/images/ext/post_tiny.png +0 -0
  249. data/public/images/ext/project_pv.png +0 -0
  250. data/public/images/ext/project_tiny.png +0 -0
  251. data/public/images/ext/tag_pv.png +0 -0
  252. data/public/images/ext/zip_pv.png +0 -0
  253. data/tasks/ann.rake +0 -80
  254. data/tasks/bones.rake +0 -20
  255. data/tasks/gem.rake +0 -201
  256. data/tasks/git.rake +0 -40
  257. data/tasks/notes.rake +0 -27
  258. data/tasks/post_load.rake +0 -34
  259. data/tasks/rdoc.rake +0 -51
  260. data/tasks/rubyforge.rake +0 -55
  261. data/tasks/setup.rb +0 -292
  262. data/tasks/spec.rake +0 -54
  263. data/tasks/svn.rake +0 -47
  264. data/tasks/test.rake +0 -40
  265. data/tasks/zentest.rake +0 -36
  266. data/test/fixtures/comments.yml +0 -126
  267. data/test/fixtures/contact_contents.yml +0 -132
  268. data/test/fixtures/data_entries.yml +0 -65
  269. data/test/fixtures/discussions.yml +0 -48
  270. data/test/fixtures/document_contents.yml +0 -108
  271. data/test/fixtures/dyn_attributes.yml +0 -66
  272. data/test/fixtures/groups.yml +0 -86
  273. data/test/fixtures/groups_users.yml +0 -81
  274. data/test/fixtures/iformats.yml +0 -29
  275. data/test/fixtures/links.yml +0 -313
  276. data/test/fixtures/nodes.yml +0 -2592
  277. data/test/fixtures/relations.yml +0 -126
  278. data/test/fixtures/sites.yml +0 -58
  279. data/test/fixtures/template_contents.yml +0 -172
  280. data/test/fixtures/users.yml +0 -167
  281. data/test/fixtures/versions.yml +0 -1911
  282. data/test/fixtures/virtual_classes.yml +0 -87
  283. data/test/fixtures/zips.yml +0 -15
  284. data/test/functional/sessions_controller_test.rb +0 -73
@@ -0,0 +1,461 @@
1
+ module Zafu
2
+ module Support
3
+ module Forms
4
+
5
+ def r_textarea
6
+ out make_textarea(@html_tag_params.merge(@params))
7
+ @html_tag_done = true
8
+ end
9
+
10
+ # <r:select name='klass' root_class='...'/>
11
+ # <r:select name='parent_id' values='projects in site'/>
12
+ # TODO: optimization (avoid loading full AR to only use [id, name])
13
+ def r_select
14
+ html_attributes, attribute = get_input_params()
15
+ return parser_error("missing name") unless attribute
16
+ if value = @params[:selected]
17
+ # FIXME: DRY with html_attributes
18
+ value = value.gsub(/\[([^\]]+)\]/) do
19
+ node_attr = $1
20
+ res = node_attribute(node_attr)
21
+ "\#{#{res}}"
22
+ end
23
+ selected = value.inspect
24
+ elsif @context[:in_filter]
25
+ selected = "params[#{attribute.to_sym.inspect}].to_s"
26
+ else
27
+ selected = "#{node_attribute(attribute)}.to_s"
28
+ end
29
+ html_id = html_attributes[:id] ? " id='#{html_attributes[:id]}'" : ''
30
+ if @context[:in_filter]
31
+ select_tag = "<select#{html_id} name='#{attribute}'>"
32
+ else
33
+ select_tag = "<select#{html_id} name='#{base_class.to_s.underscore}[#{attribute}]'>"
34
+ end
35
+
36
+ if klass = @params[:root_class]
37
+ class_opts = {}
38
+ class_opts[:without] = @params[:without] if @params[:without]
39
+ # do not use 'selected' if the node is not new
40
+ "#{select_tag}<%= options_for_select(Node.classes_for_form(:class => #{klass.inspect}#{params_to_erb(class_opts)}), (#{node}.new_record? ? #{selected} : #{node}.klass)) %></select>"
41
+ elsif @params[:type] == 'time_zone'
42
+ # <r:select name='d_tz' type='time_zone'/>
43
+ "#{select_tag}<%= options_for_select(TZInfo::Timezone.all_identifiers, #{selected}) %></select>"
44
+ elsif options_list = get_options_for_select
45
+ "#{select_tag}<%= options_for_select(#{options_list}, #{selected}) %></select>"
46
+ else
47
+ parser_error("missing 'nodes', 'root_class' or 'values'")
48
+ end
49
+ end
50
+
51
+
52
+ def r_input
53
+ html_attributes, attribute = get_input_params()
54
+ case @params[:type]
55
+ when 'select' # FIXME: why is this only for classes ?
56
+ out parser_error("please use [select] here")
57
+ r_select
58
+ when 'date_box', 'date'
59
+ return parser_error("date_box without name") unless attribute
60
+ input_id = @context[:dom_prefix] ? ", :id=>\"#{dom_id}_#{attribute}\"" : ''
61
+ "<%= date_box '#{base_class.to_s.underscore}', #{attribute.inspect}, :size=>15#{@context[:in_add] ? ", :value=>''" : ''}#{input_id} %>"
62
+ when 'id'
63
+ return parser_error("select id without name") unless attribute
64
+ name = "#{attribute}_id" unless attribute[-3..-1] == '_id'
65
+ input_id = @context[:erb_dom_id] ? ", :input_id =>\"#{erb_dom_id}_#{attribute}\"" : ''
66
+ "<%= select_id('#{base_class.to_s.underscore}', #{attribute.inspect}#{input_id}) %>"
67
+ when 'time_zone'
68
+ out parser_error("please use [select] here")
69
+ r_select
70
+ when 'submit'
71
+ @html_tag = 'input'
72
+ @html_tag_params[:type] = @params[:type]
73
+ @html_tag_params[:text] = @params[:text] if @params[:text]
74
+ @html_tag_params.merge!(html_attributes)
75
+ render_html_tag(nil)
76
+ else
77
+ # 'text', 'hidden', ...
78
+ @html_tag = 'input'
79
+ @html_tag_params[:type] = @params[:type] || 'text'
80
+ if checked = html_attributes.delete(:checked)
81
+ @html_tag_params.merge!(html_attributes)
82
+ render_html_tag(nil, checked)
83
+ else
84
+ @html_tag_params.merge!(html_attributes)
85
+ render_html_tag(nil)
86
+ end
87
+ end
88
+ end
89
+
90
+ def r_form_tag
91
+ # replace <form> with constructed form
92
+ "#{@context[:form_tag]}#{expand_with(:form_tag => nil)}</form>"
93
+ end
94
+
95
+ # TODO: add parent_id into the form !
96
+ # TODO: add <div style="margin:0;padding:0"><input name="_method" type="hidden" value="put" /></div> if method == put
97
+ # FIXME: use <r:form href='self'> or <r:form action='...'>
98
+ def r_form
99
+ hidden_fields = {}
100
+ set_fields = []
101
+ id_hash = {:class => @html_tag_params[:class] || @params[:class] || 'form'}
102
+ var_name = base_class.to_s.underscore
103
+ (descendants('input') + descendants('select')).each do |tag|
104
+ set_fields << "#{var_name}[#{tag.params[:name]}]"
105
+ end
106
+
107
+ if @context[:dom_prefix] || @params[:update]
108
+ # ajax
109
+ if @context[:in_add]
110
+ # inline form used to create new elements: set values to '' and 'parent_id' from context
111
+ id_hash[:id] = "#{erb_dom_id}_form"
112
+ id_hash[:style] = "display:none;"
113
+
114
+ cancel = "<p class='btn_x'><a href='#' onclick='[\"#{erb_dom_id}_add\", \"#{erb_dom_id}_form\"].each(Element.toggle);return false;'>#{_('btn_x')}</a></p>\n"
115
+ form = "<%= form_remote_tag(:url => #{base_class.to_s.underscore.pluralize}_path, :html => {:id => \"#{dom_id}_form_t\"}) %>\n"
116
+ else
117
+ # saved form
118
+
119
+ id_hash[:id] = erb_dom_id
120
+
121
+ cancel = !@context[:dom_prefix] ? "" : <<-END_TXT
122
+ <% if #{node}.new_record? -%>
123
+ <p class='btn_x'><a href='#' onclick='[\"<%= params[:dom_id] %>_add\", \"<%= params[:dom_id] %>_form\"].each(Element.toggle);return false;'>#{_('btn_x')}</a></p>
124
+ <% else -%>
125
+ <p class='btn_x'><%= link_to_remote(#{_('btn_x').inspect}, :url => #{base_class.to_s.underscore}_path(#{node_id}) + \"/zafu?t_url=#{CGI.escape(template_url)}&dom_id=\#{params[:dom_id]}#{@context[:need_link_id] ? "&link_id=\#{#{node}.link_id}" : ''}\", :method => :get) %></p>
126
+ <% end -%>
127
+ END_TXT
128
+ form =<<-END_TXT
129
+ <% if #{node}.new_record? -%>
130
+ <%= form_remote_tag(:url => #{base_class.to_s.underscore.pluralize}_path, :html => {:id => \"\#{params[:dom_id]}_form_t\"}) %>
131
+ <% else -%>
132
+ <%= form_remote_tag(:url => #{base_class.to_s.underscore}_path(#{node_id}), :method => :put, :html => {:id => \"#{dom_id}_form_t\"}) %>
133
+ <% end -%>
134
+ END_TXT
135
+ end
136
+
137
+ if (descendants('input') || []).select{|elem| elem.params[:type] == 'submit'} != []
138
+ # has submit
139
+ else
140
+ hidden_submit = "<input type='submit'/>" # hidden submit for Firefox compatibility
141
+ end
142
+
143
+ hidden_fields['link_id'] = "<%= #{node}.link_id %>" if @context[:need_link_id]
144
+
145
+ if @params[:update] || (@context[:add] && @context[:add].params[:update])
146
+ upd = @params[:update] || @context[:add].params[:update]
147
+ if target = find_target(upd)
148
+ hidden_fields['u_url'] = target.template_url
149
+ hidden_fields['udom_id'] = target.erb_dom_id
150
+ hidden_fields['u_id'] = "<%= #{@context[:parent_node]}.zip %>" if @context[:in_add]
151
+ hidden_fields['s'] = start_node_s_param(:value)
152
+ end
153
+ elsif (block = ancestor('block')) && node_kind_of?(DataEntry)
154
+ # updates template url
155
+ hidden_fields['u_url'] = block.template_url
156
+ hidden_fields['udom_id'] = block.erb_dom_id
157
+ end
158
+
159
+ hidden_fields['t_url'] = template_url
160
+ if t_id = @params[:t_id]
161
+ hidden_fields['t_id'] = parse_attributes_in_value(t_id)
162
+ end
163
+
164
+ erb_dom_id = @context[:saved_template] ? '<%= params[:dom_id] %>' : self.erb_dom_id
165
+
166
+ hidden_fields['dom_id'] = erb_dom_id
167
+
168
+ if node_kind_of?(Node)
169
+ hidden_fields['node[parent_id]'] = "<%= #{@context[:in_add] ? "#{@context[:parent_node]}.zip" : "#{node}.parent_zip"} %>"
170
+ elsif node_kind_of?(Comment)
171
+ # FIXME: the "... || '@node'" is a hack and I don't understand why it's needed...
172
+ hidden_fields['node_id'] = "<%= #{@context[:parent_node] || '@node'}.zip %>"
173
+ elsif node_kind_of?(DataEntry)
174
+ hidden_fields["data_entry[#{@context[:data_root]}_id]"] = "<%= #{@context[:in_add] ? @context[:parent_node] : "#{node}.#{@context[:data_root]}"}.zip %>"
175
+ end
176
+
177
+ if add_block = @context[:add]
178
+ params = add_block.params
179
+ [:after, :before, :top, :bottom].each do |sym|
180
+ if params[sym]
181
+ hidden_fields['position'] = sym.to_s
182
+ if params[sym] == 'self'
183
+ if sym == :before
184
+ hidden_fields['reference'] = "#{erb_dom_id}_add"
185
+ else
186
+ hidden_fields['reference'] = "#{erb_dom_id}_form"
187
+ end
188
+ else
189
+ hidden_fields['reference'] = params[sym]
190
+ end
191
+ break
192
+ end
193
+ end
194
+ if params[:done] == 'focus'
195
+ if params[:focus]
196
+ hidden_fields['done'] = "'$(\"#{erb_dom_id}_#{@params[:focus]}\").focus();'"
197
+ else
198
+ hidden_fields['done'] = "'$(\"#{erb_dom_id}_form_t\").focusFirstElement();'"
199
+ end
200
+ elsif params[:done]
201
+ hidden_fields['done'] = CGI.escape(params[:done]) # .gsub("NODE_ID", @node.zip).gsub("PARENT_ID", @node.parent_zip)
202
+ end
203
+ else
204
+ # ajax form, not in 'add'
205
+ hidden_fields['done'] = CGI.escape(@params[:done]) if @params[:done]
206
+ end
207
+ else
208
+ # no ajax
209
+ # FIXME
210
+ cancel = "" # link to normal node ?
211
+ form = "<form method='post' action='/nodes/#{erb_node_id}'><div style='margin:0;padding:0'><input name='_method' type='hidden' value='put' /></div>"
212
+ end
213
+
214
+ if node_kind_of?(Node) && (@params[:klass] || @context[:klass])
215
+ hidden_fields['node[klass]'] = @params[:klass] || @context[:klass]
216
+ end
217
+
218
+ if node_kind_of?(Node) && @params[:mode]
219
+ hidden_fields['mode'] = @params[:mode]
220
+ end
221
+
222
+ hidden_fields['node[v_status]'] = Zena::Status[:pub] if @context[:publish_after_save] || auto_publish_param
223
+
224
+ form << "<div class='hidden'>"
225
+ hidden_fields.each do |k,v|
226
+ next if set_fields.include?(k)
227
+ v = "'#{v}'" unless v.kind_of?(String) && ['"', "'"].include?(v[0..0])
228
+ form << "<input type='hidden' name='#{k}' value=#{v}/>\n"
229
+ end
230
+ form << hidden_submit << "\n" if hidden_submit
231
+ form << "</div>"
232
+
233
+ form << "<%= error_messages_for(#{node}) %>"
234
+
235
+ if !descendant('cancel') && !descendant('edit')
236
+ if !descendant('form_tag')
237
+ # add a descendant before blocks.
238
+ blocks_bak = @blocks
239
+ @blocks = @blocks.dup
240
+ @blocks = [make(:void, :method=>'void', :text=>cancel)] + blocks_bak
241
+ else
242
+ form = cancel + form
243
+ cancel = ''
244
+ end
245
+ end
246
+
247
+ if descendant('form_tag')
248
+ res = expand_with(:form_tag => form, :in_form => true, :form_cancel => cancel, :erb_dom_id => erb_dom_id, :dom_id => dom_id)
249
+ else
250
+ res = form + expand_with(:in_form => true, :form_cancel => cancel, :erb_dom_id => erb_dom_id, :dom_id => dom_id) + '</form>'
251
+ end
252
+
253
+ @blocks = blocks_bak if blocks_bak
254
+
255
+ @html_tag_done = false
256
+ @html_tag_params.merge!(id_hash)
257
+ out render_html_tag(res)
258
+ end
259
+
260
+ # <r:checkbox role='collaborator_for' values='projects' in='site'/>"
261
+ # TODO: implement checkbox in the same spirit as 'r_select'
262
+ def r_checkbox
263
+ return parser_error("missing 'nodes'") unless values = @params[:values] || @params[:nodes]
264
+ return parser_error("missing 'role'") unless role = (@params[:role] || @params[:name])
265
+ attribute = @params[:attr] || 'name'
266
+ if role =~ /(.*)_ids?\Z/
267
+ role = $1
268
+ end
269
+ meth = role.singularize
270
+
271
+ if values =~ /^\d+\s*($|,)/
272
+ # ids
273
+ # TODO generate the full query instead of using secure.
274
+ values = values.split(',').map{|v| v.to_i}
275
+ list_finder = "(secure(Node) { Node.find(:all, :conditions => 'zip IN (#{values.join(',')})') })"
276
+ else
277
+ # relation
278
+ list_finder, klass = build_finder_for(:all, values)
279
+ return unless list_finder
280
+ return parser_error("invalid class (#{klass})") unless klass.ancestors.include?(Node)
281
+ end
282
+ out "<% if (#{list_var} = #{list_finder}) && (#{list_var}_relation = #{node}.relation_proxy(#{role.inspect})) -%>"
283
+ out "<% if #{list_var}_relation.unique? -%>"
284
+
285
+ out "<% #{list_var}_id = #{list_var}_relation.other_id -%>"
286
+ out "<div class='input_radio'><% #{list_var}.each do |#{var}| -%>"
287
+ out "<span><input type='radio' name='node[#{meth}_id]' value='#{erb_node_id(var)}'<%= #{list_var}_id == #{var}[:id] ? \" checked='checked'\" : '' %>/> <%= #{node_attribute(attribute, :node=>var)} %></span> "
288
+ out "<% end -%></div>"
289
+ out "<input type='radio' name='node[#{meth}_id]' value=''/> #{_('none')}"
290
+
291
+ out "<% else -%>"
292
+
293
+ out "<% #{list_var}_ids = #{list_var}_relation.other_ids -%>"
294
+ out "<div class='input_checkbox'><% #{list_var}.each do |#{var}| -%>"
295
+ out "<span><input type='checkbox' name='node[#{meth}_ids][]' value='#{erb_node_id(var)}'<%= #{list_var}_ids.include?(#{var}[:id]) ? \" checked='checked'\" : '' %>/> <%= #{node_attribute(attribute, :node=>var)} %></span> "
296
+ out "<% end -%></div>"
297
+ out "<input type='hidden' name='node[#{meth}_ids][]' value=''/>"
298
+
299
+ out "<% end -%><% end -%>"
300
+ end
301
+
302
+ alias r_radio r_checkbox
303
+
304
+ protected
305
+
306
+
307
+ def get_input_params(params = @params)
308
+ res = {}
309
+ if res[:name] = (params[:name] || params[:date])
310
+ if res[:name] =~ /\A([\w_]+)\[(.*?)\]/
311
+ attribute, sub_attr = $1, $2
312
+ else
313
+ attribute = res[:name]
314
+ end
315
+
316
+ unless @context[:in_filter] || attribute == 's'
317
+ if sub_attr
318
+ res[:name] = "#{base_class.to_s.underscore}[#{attribute}][#{sub_attr}]"
319
+ else
320
+ res[:name] = "#{base_class.to_s.underscore}[#{attribute}]"
321
+ end
322
+ end
323
+
324
+ if sub_attr
325
+ if (nattr = node_attribute(attribute)) != 'nil'
326
+ nattr = "#{nattr}[#{sub_attr.inspect}]"
327
+ end
328
+ else
329
+ nattr = node_attribute(attribute)
330
+ end
331
+
332
+ if sub_attr && params[:type] == 'checkbox' && !params[:value]
333
+ # Special case when we have a sub_attribute: default value for "tagged[foobar]" is "foobar"
334
+ params[:value] = sub_attr
335
+ end
336
+
337
+ if @context[:in_add]
338
+ res[:value] = (params[:value] || params[:set_value]) ? ["'#{ helper.fquote(params[:value])}'"] : ["''"]
339
+ elsif @context[:in_filter]
340
+ res[:value] = attribute ? ["'<%= fquote params[#{attribute.to_sym.inspect}] %>'"] : ["''"]
341
+ elsif params[:value]
342
+ res[:value] = ["'#{ helper.fquote(params[:value])}'"]
343
+ else
344
+ if nattr != 'nil'
345
+ res[:value] = ["'<%= fquote #{nattr} %>'"]
346
+ else
347
+ res[:value] = ["''"]
348
+ end
349
+ end
350
+ end
351
+
352
+ if @context[:dom_prefix]
353
+ res[:id] = "#{erb_dom_id}_#{attribute}"
354
+ else
355
+ res[:id] = params[:id] if params[:id]
356
+ end
357
+
358
+ if params[:type] == 'checkbox' && nattr
359
+ if value = params[:value]
360
+ res[:checked] = "<%= #{nattr} == #{value.inspect} ? \" checked='checked'\" : '' %>"
361
+ else
362
+ res[:checked] = "<%= #{nattr}.blank? ? '' : \" checked='checked'\" %>"
363
+ end
364
+ end
365
+
366
+ [:size, :style, :class].each do |k|
367
+ res[k] = params[k] if params[k]
368
+ end
369
+
370
+ return [res, attribute]
371
+ end
372
+
373
+ def get_options_for_select
374
+ if nodes = @params[:nodes]
375
+ # TODO: dry with r_checkbox
376
+ if nodes =~ /^\d+\s*($|,)/
377
+ # ids
378
+ # TODO: optimization generate the full query instead of using secure.
379
+ nodes = nodes.split(',').map{|v| v.to_i}
380
+ nodes = "(secure(Node) { Node.find(:all, :conditions => 'zip IN (#{nodes.join(',')})') })"
381
+ else
382
+ # relation
383
+ nodes, klass = build_finder_for(:all, nodes)
384
+ return unless nodes
385
+ return parser_error("invalid class (#{klass})") unless klass.ancestors.include?(Node)
386
+ end
387
+ set_attr = @params[:attr] || 'id'
388
+ show_attr = @params[:show] || 'name'
389
+ options_list = "[['','']] + (#{nodes} || []).map{|r| [#{node_attribute(show_attr, :node => 'r', :node_class => Node)}, #{node_attribute(set_attr, :node => 'r', :node_class => Node)}.to_s]}"
390
+ elsif values = @params[:values]
391
+ options_list = values.split(',').map(&:strip)
392
+
393
+ if show = @params[:show]
394
+ show_values = show.split(',').map(&:strip)
395
+ elsif show = @params[:tshow]
396
+ show_values = show.split(',').map do |s|
397
+ _(s.strip)
398
+ end
399
+ end
400
+
401
+ if show_values
402
+ options_list.each_index do |i|
403
+ options_list[i] = [show_values[i], options_list[i]]
404
+ end
405
+ end
406
+ options_list.inspect
407
+ end
408
+ end
409
+
410
+ # transform a 'show' tag into an input field.
411
+ def make_input(params = @params)
412
+ input, attribute = get_input_params(params)
413
+ return parser_error("missing 'name'") unless attribute
414
+ return '' if attribute == 'parent_id' # set with 'r_form'
415
+ return '' if ['url','path'].include?(attribute) # cannot be set with a form
416
+ if params[:date]
417
+ input_id = @context[:dom_prefix] ? ", :id=>\"#{dom_id}_#{attribute}\"" : ''
418
+ return "<%= date_box('#{base_class.to_s.underscore}', #{params[:date].inspect}#{input_id}) %>"
419
+ end
420
+ input_id = @context[:dom_prefix] ? " id='#{erb_dom_id}_#{attribute}'" : ''
421
+ "<input type='#{params[:type] || 'text'}'#{input_id} name='#{input[:name]}' value=#{input[:value]}/>"
422
+ end
423
+
424
+ # transform a 'zazen' tag into a textarea input field.
425
+ def make_textarea(params)
426
+ return parser_error("missing 'name'") unless name = params[:name]
427
+ if name =~ /\A([\w_]+)\[(.*?)\]/
428
+ attribute = $2
429
+ else
430
+ attribute = name
431
+ name = "#{base_class.to_s.underscore}[#{attribute}]"
432
+ end
433
+ return '' if attribute == 'parent_id' # set with 'r_form'
434
+
435
+ if @blocks == [] || @blocks == ['']
436
+ if @context[:in_add]
437
+ value = ''
438
+ else
439
+ value = attribute ? "<%= #{node_attribute(attribute)} %>" : ""
440
+ end
441
+ else
442
+ value = expand_with
443
+ end
444
+ html_id = @context[:dom_prefix] ? " id='#{erb_dom_id}_#{attribute}'" : ''
445
+ "<textarea#{html_id} name='#{name}'>#{value}</textarea>"
446
+ end
447
+
448
+ def default_focus_field
449
+ if (input_fields = descendants('input')) != []
450
+ field = input_fields.first.params[:name]
451
+ elsif (show_fields = descendants('show')) != []
452
+ field = show_fields.first.params[:attr]
453
+ elsif node_kind_of?(Node)
454
+ field = 'v_title'
455
+ else
456
+ field = 'text'
457
+ end
458
+ end
459
+ end # Forms
460
+ end # Support
461
+ end # Zafu