alchemy_cms 2.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (489) hide show
  1. data/.gitignore +7 -0
  2. data/.yardopts +6 -0
  3. data/Gemfile +8 -0
  4. data/LICENSE +619 -0
  5. data/README.md +113 -0
  6. data/Rakefile +30 -0
  7. data/TODO.txt +1 -0
  8. data/alchemy.gemspec +36 -0
  9. data/app/controllers/admin/attachments_controller.rb +119 -0
  10. data/app/controllers/admin/clipboard_controller.rb +43 -0
  11. data/app/controllers/admin/contents_controller.rb +69 -0
  12. data/app/controllers/admin/elements_controller.rb +137 -0
  13. data/app/controllers/admin/essence_audios_controller.rb +14 -0
  14. data/app/controllers/admin/essence_files_controller.rb +35 -0
  15. data/app/controllers/admin/essence_flashes_controller.rb +14 -0
  16. data/app/controllers/admin/essence_pictures_controller.rb +89 -0
  17. data/app/controllers/admin/essence_videos_controller.rb +14 -0
  18. data/app/controllers/admin/languages_controller.rb +70 -0
  19. data/app/controllers/admin/layoutpages_controller.rb +11 -0
  20. data/app/controllers/admin/pages_controller.rb +244 -0
  21. data/app/controllers/admin/pictures_controller.rb +132 -0
  22. data/app/controllers/admin/trash_controller.rb +25 -0
  23. data/app/controllers/admin/users_controller.rb +75 -0
  24. data/app/controllers/admin_controller.rb +78 -0
  25. data/app/controllers/alchemy_controller.rb +239 -0
  26. data/app/controllers/attachments_controller.rb +30 -0
  27. data/app/controllers/elements_controller.rb +18 -0
  28. data/app/controllers/messages_controller.rb +98 -0
  29. data/app/controllers/pages_controller.rb +137 -0
  30. data/app/controllers/pictures_controller.rb +68 -0
  31. data/app/helpers/admin/attachments_helper.rb +7 -0
  32. data/app/helpers/admin/elements_helper.rb +28 -0
  33. data/app/helpers/admin/pages_helper.rb +3 -0
  34. data/app/helpers/admin/pictures_helper.rb +26 -0
  35. data/app/helpers/alchemy_helper.rb +1168 -0
  36. data/app/helpers/elements_helper.rb +2 -0
  37. data/app/helpers/errors_helper.rb +37 -0
  38. data/app/helpers/layout_helper.rb +37 -0
  39. data/app/helpers/pages_helper.rb +141 -0
  40. data/app/mailers/messages.rb +15 -0
  41. data/app/mailers/notifications.rb +23 -0
  42. data/app/models/attachment.rb +73 -0
  43. data/app/models/cell.rb +63 -0
  44. data/app/models/content.rb +145 -0
  45. data/app/models/element.rb +423 -0
  46. data/app/models/essence_audio.rb +17 -0
  47. data/app/models/essence_date.rb +20 -0
  48. data/app/models/essence_file.rb +17 -0
  49. data/app/models/essence_flash.rb +15 -0
  50. data/app/models/essence_html.rb +19 -0
  51. data/app/models/essence_picture.rb +27 -0
  52. data/app/models/essence_richtext.rb +50 -0
  53. data/app/models/essence_text.rb +28 -0
  54. data/app/models/essence_video.rb +17 -0
  55. data/app/models/folded_page.rb +3 -0
  56. data/app/models/language.rb +75 -0
  57. data/app/models/message.rb +57 -0
  58. data/app/models/page.rb +501 -0
  59. data/app/models/picture.rb +100 -0
  60. data/app/models/user.rb +72 -0
  61. data/app/models/user_session.rb +10 -0
  62. data/app/sweepers/content_sweeper.rb +20 -0
  63. data/app/sweepers/pages_sweeper.rb +46 -0
  64. data/app/sweepers/pictures_sweeper.rb +20 -0
  65. data/app/views/_contact.html.erb +3 -0
  66. data/app/views/_intro.html.erb +3 -0
  67. data/app/views/_news.html.erb +3 -0
  68. data/app/views/_newsletter_layout.html.erb +1 -0
  69. data/app/views/_search.html.erb +3 -0
  70. data/app/views/_standard.html.erb +1 -0
  71. data/app/views/admin/attachments/_attachment.html.erb +58 -0
  72. data/app/views/admin/attachments/_file_to_assign.html.erb +20 -0
  73. data/app/views/admin/attachments/_files_list.html.erb +24 -0
  74. data/app/views/admin/attachments/archive_overlay.html.erb +8 -0
  75. data/app/views/admin/attachments/create.js.erb +6 -0
  76. data/app/views/admin/attachments/edit.html.erb +12 -0
  77. data/app/views/admin/attachments/index.html.erb +30 -0
  78. data/app/views/admin/attachments/new.html.erb +11 -0
  79. data/app/views/admin/clipboard/clear.js.erb +6 -0
  80. data/app/views/admin/clipboard/index.html.erb +19 -0
  81. data/app/views/admin/clipboard/insert.js.erb +14 -0
  82. data/app/views/admin/clipboard/remove.js.erb +10 -0
  83. data/app/views/admin/contents/_missing.html.erb +20 -0
  84. data/app/views/admin/contents/create.js.erb +93 -0
  85. data/app/views/admin/contents/new.html.erb +15 -0
  86. data/app/views/admin/elements/_add_content.html.erb +16 -0
  87. data/app/views/admin/elements/_element.html.erb +22 -0
  88. data/app/views/admin/elements/_element_foot.html.erb +35 -0
  89. data/app/views/admin/elements/_element_head.html.erb +29 -0
  90. data/app/views/admin/elements/_elements_select.html.erb +8 -0
  91. data/app/views/admin/elements/_new_element_form.html.erb +25 -0
  92. data/app/views/admin/elements/_picture_editor.html.erb +25 -0
  93. data/app/views/admin/elements/create.js.erb +20 -0
  94. data/app/views/admin/elements/destroy.js.erb +6 -0
  95. data/app/views/admin/elements/fold.js.erb +37 -0
  96. data/app/views/admin/elements/index.html.erb +33 -0
  97. data/app/views/admin/elements/list.js.erb +20 -0
  98. data/app/views/admin/elements/new.html.erb +33 -0
  99. data/app/views/admin/elements/order.js.erb +7 -0
  100. data/app/views/admin/elements/trash.js.erb +13 -0
  101. data/app/views/admin/elements/update.js.erb +10 -0
  102. data/app/views/admin/essence_files/edit.html.erb +91 -0
  103. data/app/views/admin/essence_pictures/assign.js.erb +15 -0
  104. data/app/views/admin/essence_pictures/crop.html.erb +36 -0
  105. data/app/views/admin/essence_pictures/destroy.js.erb +17 -0
  106. data/app/views/admin/essence_pictures/edit.html.erb +75 -0
  107. data/app/views/admin/essence_pictures/update.js.erb +16 -0
  108. data/app/views/admin/index.html.erb +92 -0
  109. data/app/views/admin/infos.html.erb +5 -0
  110. data/app/views/admin/languages/_form.html.erb +34 -0
  111. data/app/views/admin/languages/_language.html.erb +35 -0
  112. data/app/views/admin/languages/edit.html.erb +1 -0
  113. data/app/views/admin/languages/index.html.erb +41 -0
  114. data/app/views/admin/languages/new.html.erb +1 -0
  115. data/app/views/admin/layoutpages/_layoutpage.html.erb +80 -0
  116. data/app/views/admin/layoutpages/index.html.erb +75 -0
  117. data/app/views/admin/leave.html.erb +11 -0
  118. data/app/views/admin/login.html.erb +46 -0
  119. data/app/views/admin/logout.html.erb +5 -0
  120. data/app/views/admin/pages/_contactform_links.html.erb +66 -0
  121. data/app/views/admin/pages/_create_language_form.html.erb +42 -0
  122. data/app/views/admin/pages/_external_link.html.erb +54 -0
  123. data/app/views/admin/pages/_file_link.html.erb +52 -0
  124. data/app/views/admin/pages/_internal_link.html.erb +47 -0
  125. data/app/views/admin/pages/_new_page_form.html.erb +29 -0
  126. data/app/views/admin/pages/_page.html.erb +114 -0
  127. data/app/views/admin/pages/_page_for_links.html.erb +43 -0
  128. data/app/views/admin/pages/_page_infos.html.erb +3 -0
  129. data/app/views/admin/pages/_page_status.html.erb +9 -0
  130. data/app/views/admin/pages/_sitemap.html.erb +99 -0
  131. data/app/views/admin/pages/configure.html.erb +71 -0
  132. data/app/views/admin/pages/configure_external.html.erb +40 -0
  133. data/app/views/admin/pages/destroy.js.erb +12 -0
  134. data/app/views/admin/pages/edit.html.erb +185 -0
  135. data/app/views/admin/pages/flush.js.erb +2 -0
  136. data/app/views/admin/pages/fold.js.erb +4 -0
  137. data/app/views/admin/pages/index.html.erb +108 -0
  138. data/app/views/admin/pages/link.html.erb +30 -0
  139. data/app/views/admin/pages/locked.html.erb +3 -0
  140. data/app/views/admin/pages/new.html.erb +50 -0
  141. data/app/views/admin/pages/show.html.erb +1 -0
  142. data/app/views/admin/pages/sort.js.erb +6 -0
  143. data/app/views/admin/pages/unlock.js.erb +8 -0
  144. data/app/views/admin/pages/update.js.erb +19 -0
  145. data/app/views/admin/partials/_flash.html.erb +4 -0
  146. data/app/views/admin/partials/_flash_notices.html.erb +5 -0
  147. data/app/views/admin/partials/_mainnavigation_entry.html.erb +27 -0
  148. data/app/views/admin/partials/_pagination_links.html.erb +7 -0
  149. data/app/views/admin/partials/_per_page_links.html.erb +17 -0
  150. data/app/views/admin/partials/_remote_pagination_links.html.erb +11 -0
  151. data/app/views/admin/partials/_remote_search_form.html.erb +36 -0
  152. data/app/views/admin/partials/_search_form.html.erb +17 -0
  153. data/app/views/admin/partials/_sub_navigation.html.erb +14 -0
  154. data/app/views/admin/partials/_upload_form.html.erb +116 -0
  155. data/app/views/admin/pictures/_archive_overlay_images.html.erb +17 -0
  156. data/app/views/admin/pictures/_filter_and_size_bar.html.erb +88 -0
  157. data/app/views/admin/pictures/_picture.html.erb +36 -0
  158. data/app/views/admin/pictures/_picture_to_assign.html.erb +32 -0
  159. data/app/views/admin/pictures/_pictures_list.html.erb +12 -0
  160. data/app/views/admin/pictures/archive_overlay.html.erb +3 -0
  161. data/app/views/admin/pictures/create.js.erb +12 -0
  162. data/app/views/admin/pictures/index.html.erb +56 -0
  163. data/app/views/admin/pictures/new.html.erb +11 -0
  164. data/app/views/admin/pictures/show_in_window.html.erb +1 -0
  165. data/app/views/admin/pictures/update.js.erb +11 -0
  166. data/app/views/admin/signup.html.erb +16 -0
  167. data/app/views/admin/trash/index.html.erb +25 -0
  168. data/app/views/admin/users/_table.html.erb +54 -0
  169. data/app/views/admin/users/_user.html.erb +36 -0
  170. data/app/views/admin/users/edit.html.erb +6 -0
  171. data/app/views/admin/users/index.html.erb +41 -0
  172. data/app/views/admin/users/new.html.erb +6 -0
  173. data/app/views/attachments/show.html.erb +1 -0
  174. data/app/views/elements/_article_editor.html.erb +4 -0
  175. data/app/views/elements/_article_view.html.erb +25 -0
  176. data/app/views/elements/_bild_editor.html.erb +1 -0
  177. data/app/views/elements/_bild_text_editor.html.erb +2 -0
  178. data/app/views/elements/_bild_text_view.html.erb +9 -0
  179. data/app/views/elements/_bild_view.html.erb +9 -0
  180. data/app/views/elements/_claim_editor.html.erb +1 -0
  181. data/app/views/elements/_claim_view.html.erb +1 -0
  182. data/app/views/elements/_contactform_editor.html.erb +7 -0
  183. data/app/views/elements/_contactform_view.html.erb +92 -0
  184. data/app/views/elements/_editor_not_found.html.erb +5 -0
  185. data/app/views/elements/_footnote_editor.html.erb +1 -0
  186. data/app/views/elements/_footnote_view.html.erb +5 -0
  187. data/app/views/elements/_header_editor.html.erb +1 -0
  188. data/app/views/elements/_header_view.html.erb +1 -0
  189. data/app/views/elements/_headline_editor.html.erb +1 -0
  190. data/app/views/elements/_headline_view.html.erb +1 -0
  191. data/app/views/elements/_image_mosaic_editor.html.erb +2 -0
  192. data/app/views/elements/_image_mosaic_view.html.erb +12 -0
  193. data/app/views/elements/_intro_editor.html.erb +1 -0
  194. data/app/views/elements/_intro_image_text_editor.html.erb +3 -0
  195. data/app/views/elements/_intro_image_text_view.html.erb +16 -0
  196. data/app/views/elements/_intro_view.html.erb +3 -0
  197. data/app/views/elements/_news_editor.html.erb +3 -0
  198. data/app/views/elements/_news_view.html.erb +11 -0
  199. data/app/views/elements/_searchresult_editor.html.erb +1 -0
  200. data/app/views/elements/_searchresult_view.html.erb +42 -0
  201. data/app/views/elements/_sitemap_editor.html.erb +3 -0
  202. data/app/views/elements/_sitemap_view.html.erb +38 -0
  203. data/app/views/elements/_sitename_editor.html.erb +1 -0
  204. data/app/views/elements/_sitename_view.html.erb +1 -0
  205. data/app/views/elements/_subheadline_editor.html.erb +1 -0
  206. data/app/views/elements/_subheadline_view.html.erb +5 -0
  207. data/app/views/elements/_text_editor.html.erb +1 -0
  208. data/app/views/elements/_text_view.html.erb +3 -0
  209. data/app/views/elements/_view_not_found.html.erb +1 -0
  210. data/app/views/elements/show.html.erb +6 -0
  211. data/app/views/elements/show.js.erb +11 -0
  212. data/app/views/essences/_essence_audio_editor.html.erb +1 -0
  213. data/app/views/essences/_essence_audio_view.html.erb +33 -0
  214. data/app/views/essences/_essence_date_editor.html.erb +12 -0
  215. data/app/views/essences/_essence_date_view.html.erb +7 -0
  216. data/app/views/essences/_essence_file_editor.html.erb +63 -0
  217. data/app/views/essences/_essence_file_view.html.erb +6 -0
  218. data/app/views/essences/_essence_flash_editor.html.erb +1 -0
  219. data/app/views/essences/_essence_flash_view.html.erb +26 -0
  220. data/app/views/essences/_essence_html_editor.html.erb +8 -0
  221. data/app/views/essences/_essence_html_view.html.erb +1 -0
  222. data/app/views/essences/_essence_picture_editor.html.erb +70 -0
  223. data/app/views/essences/_essence_picture_tools.html.erb +60 -0
  224. data/app/views/essences/_essence_picture_view.html.erb +42 -0
  225. data/app/views/essences/_essence_richtext_editor.html.erb +9 -0
  226. data/app/views/essences/_essence_richtext_view.html.erb +5 -0
  227. data/app/views/essences/_essence_text_editor.html.erb +82 -0
  228. data/app/views/essences/_essence_text_view.html.erb +11 -0
  229. data/app/views/essences/_essence_video_editor.html.erb +1 -0
  230. data/app/views/essences/_essence_video_view.html.erb +35 -0
  231. data/app/views/layouts/alchemy.html.erb +60 -0
  232. data/app/views/layouts/login.html.erb +60 -0
  233. data/app/views/layouts/pages.html.erb +31 -0
  234. data/app/views/layouts/sitemap.xml.erb +4 -0
  235. data/app/views/messages/mail.text.erb +10 -0
  236. data/app/views/messages/new.html.erb +1 -0
  237. data/app/views/notifications/admin_user_created.text.erb +13 -0
  238. data/app/views/notifications/registered_user_created.text.erb +10 -0
  239. data/app/views/page_layouts/_contact.html.erb +14 -0
  240. data/app/views/page_layouts/_external.html.erb +1 -0
  241. data/app/views/page_layouts/_intro.html.erb +14 -0
  242. data/app/views/page_layouts/_layout_footer.html.erb +14 -0
  243. data/app/views/page_layouts/_layout_header.html.erb +14 -0
  244. data/app/views/page_layouts/_news.html.erb +14 -0
  245. data/app/views/page_layouts/_newsletter_layout.html.erb +1 -0
  246. data/app/views/page_layouts/_search.html.erb +14 -0
  247. data/app/views/page_layouts/_standard.html.erb +14 -0
  248. data/app/views/pages/show.html.erb +1 -0
  249. data/app/views/pages/show.rss.builder +27 -0
  250. data/app/views/pages/sitemap.xml.erb +8 -0
  251. data/app/views/partials/_navigation_image_link.html.erb +14 -0
  252. data/app/views/partials/_navigation_link.html.erb +20 -0
  253. data/app/views/partials/_navigation_renderer.html.erb +23 -0
  254. data/app/views/pictures/show.gif.flexi +19 -0
  255. data/app/views/pictures/show.jpg.flexi +19 -0
  256. data/app/views/pictures/show.png.flexi +19 -0
  257. data/app/views/pictures/thumbnail.png.flexi +13 -0
  258. data/app/views/pictures/zoom.png.flexi +3 -0
  259. data/assets/images/ajax_loader.gif +0 -0
  260. data/assets/images/alchemy-logo.png +0 -0
  261. data/assets/images/flags.png +0 -0
  262. data/assets/images/gui/navi-tab.png +0 -0
  263. data/assets/images/gui/shading.png +0 -0
  264. data/assets/images/gui/shading_90.png +0 -0
  265. data/assets/images/gui/toggle.png +0 -0
  266. data/assets/images/icons.png +0 -0
  267. data/assets/images/jquery-sb/select_arrow.gif +0 -0
  268. data/assets/images/jquery-sb/select_arrow_bg.gif +0 -0
  269. data/assets/images/jquery-sb/select_arrow_bg_hover.gif +0 -0
  270. data/assets/images/jquery-ui/ui-icons_666666_256x240.png +0 -0
  271. data/assets/images/placeholder.png +0 -0
  272. data/assets/images/swfupload/browse_button.png +0 -0
  273. data/assets/javascripts/alchemy.element_editor_selector.js +88 -0
  274. data/assets/javascripts/alchemy.growler.js +44 -0
  275. data/assets/javascripts/alchemy.image_cropper.js +56 -0
  276. data/assets/javascripts/alchemy.js +892 -0
  277. data/assets/javascripts/alchemy.link_overlay.js +221 -0
  278. data/assets/javascripts/alchemy.page_sorter.js +42 -0
  279. data/assets/javascripts/alchemy.preview.js +145 -0
  280. data/assets/javascripts/jquery-ui.js +428 -0
  281. data/assets/javascripts/jquery.Jcrop.min.js +246 -0
  282. data/assets/javascripts/jquery.dialogextend.min.js +8 -0
  283. data/assets/javascripts/jquery.in-place-edit.js +171 -0
  284. data/assets/javascripts/jquery.js +18 -0
  285. data/assets/javascripts/jquery.rails.js +315 -0
  286. data/assets/javascripts/jquery.sb.min.js +14 -0
  287. data/assets/javascripts/jquery.scrollTo-1.4.2-min.js +11 -0
  288. data/assets/javascripts/jquery.ui.nestedSortable.js +291 -0
  289. data/assets/javascripts/jquery.ui.tabspaging.js +281 -0
  290. data/assets/javascripts/swfupload/fileprogress.js +203 -0
  291. data/assets/javascripts/swfupload/handlers.js +171 -0
  292. data/assets/javascripts/swfupload/queue.js +98 -0
  293. data/assets/javascripts/swfupload/swfupload.js +980 -0
  294. data/assets/javascripts/swfupload/swfupload.swf +0 -0
  295. data/assets/javascripts/tiny_mce/jquery.tinymce.js +1 -0
  296. data/assets/javascripts/tiny_mce/langs/de.js +1 -0
  297. data/assets/javascripts/tiny_mce/langs/en.js +223 -0
  298. data/assets/javascripts/tiny_mce/license.txt +504 -0
  299. data/assets/javascripts/tiny_mce/plugins/alchemy_link/editor_plugin.js +43 -0
  300. data/assets/javascripts/tiny_mce/plugins/alchemy_link/langs/de.js +4 -0
  301. data/assets/javascripts/tiny_mce/plugins/alchemy_link/langs/en.js +4 -0
  302. data/assets/javascripts/tiny_mce/plugins/fullscreen/editor_plugin.js +1 -0
  303. data/assets/javascripts/tiny_mce/plugins/fullscreen/fullscreen.htm +109 -0
  304. data/assets/javascripts/tiny_mce/plugins/inlinepopups/editor_plugin.js +1 -0
  305. data/assets/javascripts/tiny_mce/plugins/inlinepopups/skins/alchemy/window.css +402 -0
  306. data/assets/javascripts/tiny_mce/plugins/inlinepopups/template.htm +387 -0
  307. data/assets/javascripts/tiny_mce/plugins/lists/editor_plugin.js +1 -0
  308. data/assets/javascripts/tiny_mce/plugins/paste/editor_plugin.js +1 -0
  309. data/assets/javascripts/tiny_mce/plugins/paste/js/pastetext.js +36 -0
  310. data/assets/javascripts/tiny_mce/plugins/paste/js/pasteword.js +51 -0
  311. data/assets/javascripts/tiny_mce/plugins/paste/langs/de_dlg.js +1 -0
  312. data/assets/javascripts/tiny_mce/plugins/paste/langs/en_dlg.js +5 -0
  313. data/assets/javascripts/tiny_mce/plugins/paste/pastetext.htm +27 -0
  314. data/assets/javascripts/tiny_mce/plugins/paste/pasteword.htm +21 -0
  315. data/assets/javascripts/tiny_mce/plugins/table/cell.htm +180 -0
  316. data/assets/javascripts/tiny_mce/plugins/table/css/cell.css +17 -0
  317. data/assets/javascripts/tiny_mce/plugins/table/css/row.css +25 -0
  318. data/assets/javascripts/tiny_mce/plugins/table/css/table.css +13 -0
  319. data/assets/javascripts/tiny_mce/plugins/table/editor_plugin.js +1 -0
  320. data/assets/javascripts/tiny_mce/plugins/table/js/cell.js +319 -0
  321. data/assets/javascripts/tiny_mce/plugins/table/js/merge_cells.js +27 -0
  322. data/assets/javascripts/tiny_mce/plugins/table/js/row.js +237 -0
  323. data/assets/javascripts/tiny_mce/plugins/table/js/table.js +450 -0
  324. data/assets/javascripts/tiny_mce/plugins/table/langs/de_dlg.js +1 -0
  325. data/assets/javascripts/tiny_mce/plugins/table/langs/en_dlg.js +75 -0
  326. data/assets/javascripts/tiny_mce/plugins/table/merge_cells.htm +32 -0
  327. data/assets/javascripts/tiny_mce/plugins/table/row.htm +158 -0
  328. data/assets/javascripts/tiny_mce/plugins/table/table.htm +188 -0
  329. data/assets/javascripts/tiny_mce/themes/advanced/about.htm +52 -0
  330. data/assets/javascripts/tiny_mce/themes/advanced/anchor.htm +26 -0
  331. data/assets/javascripts/tiny_mce/themes/advanced/charmap.htm +51 -0
  332. data/assets/javascripts/tiny_mce/themes/advanced/color_picker.htm +74 -0
  333. data/assets/javascripts/tiny_mce/themes/advanced/editor_template.js +1 -0
  334. data/assets/javascripts/tiny_mce/themes/advanced/image.htm +80 -0
  335. data/assets/javascripts/tiny_mce/themes/advanced/img/colorpicker.jpg +0 -0
  336. data/assets/javascripts/tiny_mce/themes/advanced/img/flash.gif +0 -0
  337. data/assets/javascripts/tiny_mce/themes/advanced/img/icons.gif +0 -0
  338. data/assets/javascripts/tiny_mce/themes/advanced/img/iframe.gif +0 -0
  339. data/assets/javascripts/tiny_mce/themes/advanced/img/pagebreak.gif +0 -0
  340. data/assets/javascripts/tiny_mce/themes/advanced/img/quicktime.gif +0 -0
  341. data/assets/javascripts/tiny_mce/themes/advanced/img/realmedia.gif +0 -0
  342. data/assets/javascripts/tiny_mce/themes/advanced/img/shockwave.gif +0 -0
  343. data/assets/javascripts/tiny_mce/themes/advanced/img/trans.gif +0 -0
  344. data/assets/javascripts/tiny_mce/themes/advanced/img/video.gif +0 -0
  345. data/assets/javascripts/tiny_mce/themes/advanced/img/windowsmedia.gif +0 -0
  346. data/assets/javascripts/tiny_mce/themes/advanced/js/about.js +73 -0
  347. data/assets/javascripts/tiny_mce/themes/advanced/js/anchor.js +42 -0
  348. data/assets/javascripts/tiny_mce/themes/advanced/js/charmap.js +355 -0
  349. data/assets/javascripts/tiny_mce/themes/advanced/js/color_picker.js +329 -0
  350. data/assets/javascripts/tiny_mce/themes/advanced/js/image.js +247 -0
  351. data/assets/javascripts/tiny_mce/themes/advanced/js/link.js +153 -0
  352. data/assets/javascripts/tiny_mce/themes/advanced/js/source_editor.js +56 -0
  353. data/assets/javascripts/tiny_mce/themes/advanced/langs/de.js +1 -0
  354. data/assets/javascripts/tiny_mce/themes/advanced/langs/de_dlg.js +1 -0
  355. data/assets/javascripts/tiny_mce/themes/advanced/langs/en.js +68 -0
  356. data/assets/javascripts/tiny_mce/themes/advanced/langs/en_dlg.js +54 -0
  357. data/assets/javascripts/tiny_mce/themes/advanced/link.htm +57 -0
  358. data/assets/javascripts/tiny_mce/themes/advanced/shortcuts.htm +47 -0
  359. data/assets/javascripts/tiny_mce/themes/advanced/skins/default/content.css +47 -0
  360. data/assets/javascripts/tiny_mce/themes/advanced/skins/default/dialog.css +117 -0
  361. data/assets/javascripts/tiny_mce/themes/advanced/skins/default/img/buttons.png +0 -0
  362. data/assets/javascripts/tiny_mce/themes/advanced/skins/default/img/items.gif +0 -0
  363. data/assets/javascripts/tiny_mce/themes/advanced/skins/default/img/menu_arrow.gif +0 -0
  364. data/assets/javascripts/tiny_mce/themes/advanced/skins/default/img/menu_check.gif +0 -0
  365. data/assets/javascripts/tiny_mce/themes/advanced/skins/default/img/progress.gif +0 -0
  366. data/assets/javascripts/tiny_mce/themes/advanced/skins/default/img/tabs.gif +0 -0
  367. data/assets/javascripts/tiny_mce/themes/advanced/skins/default/ui.css +214 -0
  368. data/assets/javascripts/tiny_mce/themes/advanced/skins/highcontrast/content.css +23 -0
  369. data/assets/javascripts/tiny_mce/themes/advanced/skins/highcontrast/dialog.css +105 -0
  370. data/assets/javascripts/tiny_mce/themes/advanced/skins/highcontrast/ui.css +102 -0
  371. data/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/content.css +46 -0
  372. data/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/dialog.css +117 -0
  373. data/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/img/button_bg.png +0 -0
  374. data/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_black.png +0 -0
  375. data/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_silver.png +0 -0
  376. data/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/ui.css +217 -0
  377. data/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/ui_black.css +8 -0
  378. data/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css +5 -0
  379. data/assets/javascripts/tiny_mce/themes/advanced/source_editor.htm +25 -0
  380. data/assets/javascripts/tiny_mce/themes/simple/langs/de.js +1 -0
  381. data/assets/javascripts/tiny_mce/tiny_mce.js +1 -0
  382. data/assets/javascripts/tiny_mce/tiny_mce_popup.js +5 -0
  383. data/assets/javascripts/tiny_mce/utils/editable_selects.js +70 -0
  384. data/assets/javascripts/tiny_mce/utils/form_utils.js +210 -0
  385. data/assets/javascripts/tiny_mce/utils/mctabs.js +162 -0
  386. data/assets/javascripts/tiny_mce/utils/validate.js +252 -0
  387. data/assets/stylesheets/Jcrop.gif +0 -0
  388. data/assets/stylesheets/alchemy.css +3629 -0
  389. data/assets/stylesheets/alchemy_tinymce_content.css +94 -0
  390. data/assets/stylesheets/alchemy_tinymce_dialog.css +415 -0
  391. data/assets/stylesheets/default/img/tabs.gif +0 -0
  392. data/assets/stylesheets/elements.css +900 -0
  393. data/assets/stylesheets/flags.css +1 -0
  394. data/assets/stylesheets/ie6.css +18 -0
  395. data/assets/stylesheets/jquery-ui-1.8.7.alchemy.css +2023 -0
  396. data/assets/stylesheets/jquery.Jcrop.css +35 -0
  397. data/assets/stylesheets/jquery.sb.css +244 -0
  398. data/assets/stylesheets/standard_set.css +374 -0
  399. data/bin/alchemy +347 -0
  400. data/config/alchemy/config.yml +199 -0
  401. data/config/alchemy/elements.yml +219 -0
  402. data/config/alchemy/page_layouts.yml +65 -0
  403. data/config/asset_packages.yml +32 -0
  404. data/config/authorization_rules.rb +96 -0
  405. data/config/initializers/authorization.rb +4 -0
  406. data/config/initializers/cache_storage.rb +1 -0
  407. data/config/initializers/fast_gettext.rb +2 -0
  408. data/config/initializers/tiny_mce_hammer.rb +32 -0
  409. data/config/locales/de.yml +370 -0
  410. data/config/locales/en.yml +364 -0
  411. data/config/routes.rb +141 -0
  412. data/db/migrate/20100607143125_create_pages.rb +34 -0
  413. data/db/migrate/20100607144254_create_elements.rb +20 -0
  414. data/db/migrate/20100607145256_create_contents.rb +18 -0
  415. data/db/migrate/20100607145719_create_users.rb +32 -0
  416. data/db/migrate/20100607150611_create_pictures.rb +16 -0
  417. data/db/migrate/20100607150812_create_attachments.rb +16 -0
  418. data/db/migrate/20100607153647_create_folded_pages.rb +13 -0
  419. data/db/migrate/20100607161345_create_essence_texts.rb +19 -0
  420. data/db/migrate/20100607162339_create_elements_pages.rb +12 -0
  421. data/db/migrate/20100607193638_create_essence_pictures.rb +23 -0
  422. data/db/migrate/20100607193646_create_essence_richtexts.rb +16 -0
  423. data/db/migrate/20100607193653_create_essence_htmls.rb +13 -0
  424. data/db/migrate/20100609111653_create_essence_dates.rb +13 -0
  425. data/db/migrate/20100609111809_create_essence_files.rb +15 -0
  426. data/db/migrate/20100609111821_create_essence_flashes.rb +16 -0
  427. data/db/migrate/20100609111837_create_essence_videos.rb +18 -0
  428. data/db/migrate/20100616150753_create_essence_audios.rb +17 -0
  429. data/db/migrate/20100812085225_add_crop_from_and_crop_size_to_essence_pictures.rb +11 -0
  430. data/db/migrate/20100909140701_change_essence_htmls_source_column_type.rb +9 -0
  431. data/db/migrate/20101109150312_alter_pages_visible_column_default.rb +9 -0
  432. data/db/migrate/20101109151812_create_languages.rb +19 -0
  433. data/db/migrate/20101216151419_add_language_id_to_pages.rb +19 -0
  434. data/db/migrate/20101216155216_add_index_to_languages.rb +9 -0
  435. data/db/migrate/20101216173323_add_default_to_languages.rb +9 -0
  436. data/db/migrate/20101218130049_add_urlname_index_to_pages.rb +9 -0
  437. data/db/migrate/20110115123343_remove_css_class_default_from_essence_pictures.rb +11 -0
  438. data/db/migrate/20110224105120_change_pages_visible_default.rb +11 -0
  439. data/db/migrate/20110228182659_remove_default_page_layout_from_pages.rb +11 -0
  440. data/db/migrate/20110414163140_remove_display_name_from_elements.rb +11 -0
  441. data/db/migrate/20110511100516_rename_essence_texts_title_to_link_title.rb +9 -0
  442. data/db/migrate/20110529130429_create_cells.rb +14 -0
  443. data/db/migrate/20110529130500_add_cell_id_to_elements.rb +11 -0
  444. data/db/migrate/20110530102804_change_pages_page_layout_column.rb +11 -0
  445. data/db/migrate/20110707190728_add_render_size_to_essence_pictures.rb +9 -0
  446. data/db/migrate/20110711142057_change_open_link_in_new_window_to_link_target.rb +19 -0
  447. data/lib/alchemy.rb +24 -0
  448. data/lib/alchemy/config.rb +51 -0
  449. data/lib/alchemy/controller.rb +79 -0
  450. data/lib/alchemy/engine.rb +29 -0
  451. data/lib/alchemy/essence.rb +178 -0
  452. data/lib/alchemy/file_utilz.rb +73 -0
  453. data/lib/alchemy/page_layout.rb +66 -0
  454. data/lib/alchemy/remote_pagination_link_renderer.rb +17 -0
  455. data/lib/alchemy/seeder.rb +112 -0
  456. data/lib/alchemy/version.rb +5 -0
  457. data/lib/extensions/action_view.rb +17 -0
  458. data/lib/extensions/array.rb +25 -0
  459. data/lib/extensions/hash.rb +34 -0
  460. data/lib/middleware/flash_session_cookie.rb +22 -0
  461. data/lib/rails/generators/alchemy/elements/elements_generator.rb +35 -0
  462. data/lib/rails/generators/alchemy/elements/templates/editor.html.erb +9 -0
  463. data/lib/rails/generators/alchemy/elements/templates/view.html.erb +21 -0
  464. data/lib/rails/generators/alchemy/page_layouts/page_layouts_generator.rb +32 -0
  465. data/lib/rails/generators/alchemy/page_layouts/templates/layout.html.erb +1 -0
  466. data/lib/rails/generators/alchemy/plugin/plugin_generator.rb +29 -0
  467. data/lib/rails/generators/alchemy/plugin/templates/authorization_rules.rb +5 -0
  468. data/lib/rails/generators/alchemy/plugin/templates/config.yml +30 -0
  469. data/lib/rails/generators/alchemy/plugin/templates/init.rb +4 -0
  470. data/lib/rails/generators/alchemy/plugin/templates/routes.rb +4 -0
  471. data/lib/rails/generators/alchemy/scaffold/scaffold_generator.rb +35 -0
  472. data/lib/rails/generators/alchemy/scaffold/templates/elements.yml +91 -0
  473. data/lib/rails/generators/alchemy/scaffold/templates/page_layouts.yml +29 -0
  474. data/lib/rails/templates/alchemy.rb +14 -0
  475. data/lib/tasks/fleximage.rake +154 -0
  476. data/lib/tasks/gettext.rake +75 -0
  477. data/lib/tasks/install.rake +123 -0
  478. data/lib/tasks/upgrade.rake +211 -0
  479. data/lib/translation_extras/alchemy_core_modules.rb +11 -0
  480. data/lib/vendor/i18n_label.rb +23 -0
  481. data/locale/alchemy.pot +1728 -0
  482. data/locale/de/LC_MESSAGES/alchemy.mo +0 -0
  483. data/locale/de/alchemy.po +1774 -0
  484. data/locale/en/LC_MESSAGES/alchemy.mo +0 -0
  485. data/locale/en/alchemy.po +1742 -0
  486. data/locale/missing_translations.rb +4 -0
  487. data/locale/model_attributes.rb +56 -0
  488. data/recipes/alchemy_capistrano_tasks.rb +83 -0
  489. metadata +769 -0
@@ -0,0 +1,30 @@
1
+ class AttachmentsController < AlchemyController
2
+
3
+ unloadable
4
+
5
+ # sends file inline. i.e. for viewing pdfs/movies in browser
6
+ def show
7
+ @attachment = Attachment.find(params[:id])
8
+ send_file(
9
+ @attachment.public_filename,
10
+ {
11
+ :name => @attachment.filename,
12
+ :type => @attachment.content_type,
13
+ :disposition => 'inline'
14
+ }
15
+ )
16
+ end
17
+
18
+ # sends file as attachment. aka download
19
+ def download
20
+ @attachment = Attachment.find(params[:id])
21
+ send_file(
22
+ @attachment.full_filename, {
23
+ :name => @attachment.filename,
24
+ :type => @attachment.content_type,
25
+ :disposition => 'attachment'
26
+ }
27
+ )
28
+ end
29
+
30
+ end
@@ -0,0 +1,18 @@
1
+ class ElementsController < AlchemyController
2
+
3
+ unloadable
4
+
5
+ filter_access_to [:show], :attribute_check => true
6
+ layout false
7
+
8
+ # Returns the element partial as HTML or as JavaScript that tries to replace a given +container_id+ with the partial content via jQuery.
9
+ def show
10
+ @element = Element.find(params[:id])
11
+ @page = @element.page
12
+ respond_to do |format|
13
+ format.html
14
+ format.js
15
+ end
16
+ end
17
+
18
+ end
@@ -0,0 +1,98 @@
1
+ # == Sending Messages:
2
+ # To send Messages via contact forms you can create your form fields in the config.yml
3
+ # === Example:
4
+ # Make an Element with this options inside your elements.yml file:
5
+ #
6
+ # - name: contact
7
+ # display_name: Kontaktformular
8
+ # contents:
9
+ # - name: mail_to
10
+ # type: EssenceText
11
+ # - name: subject
12
+ # type: EssenceText
13
+ # - name: mail_from
14
+ # type: EssenceText
15
+ # - name: success_page
16
+ # type: EssenceText
17
+ #
18
+ # The fields mail_to, mail_from, subject and success_page are recommended.
19
+ # The MessagesController uses them to send your mails. So your customer has full controll of these values inside his contactform element.
20
+ #
21
+ # Then make a page layout for your contact page in the page_layouts.yml file:
22
+ #
23
+ # - name: contact
24
+ # display_name: Kontakt
25
+ # unique: true
26
+ # cache: false
27
+ # elements: [pageheading, heading, contact, bild, absatz, file_download]
28
+ # autogenerate: [contact]
29
+ #
30
+ # Disabling the page caching is stronlgy recommended!
31
+ #
32
+ # The editor view for your element should have this layout:
33
+ #
34
+ # <%= render_essence_editor_by_name(element, 'mail_from') %>
35
+ # <%= render_essence_editor_by_name(element, 'mail_to') %>
36
+ # <%= render_essence_editor_by_name(element, 'subject') %>
37
+ # <p>
38
+ # Folgeseite: <%= page_selector(element, 'success_page') %>
39
+ # </p>
40
+ #
41
+ # Please have a look at the vendor/plugins/alchemy/config/config.yml file for further Message settings.
42
+
43
+ class MessagesController < AlchemyController
44
+
45
+ unloadable
46
+
47
+ helper :pages
48
+
49
+ def new#:nodoc:
50
+ @message = Message.new
51
+ @page = Page.find_by_page_layout(Alchemy::Config.get(:mailer)[:form_layout_name])
52
+ @root_page = Page.language_root_for(session[:language_id])
53
+ raise "Page for page_layout #{configuration(:mailer)[:page_layout_name]} not found" if @page.blank?
54
+ render :template => '/pages/show', :layout => 'pages'
55
+ end
56
+
57
+ def index#:nodoc:
58
+ @page = Page.find_by_page_layout(configuration(:mailer)[:page_layout_name])
59
+ raise "Page for page_layout #{configuration(:mailer)[:page_layout_name]} not found" if @page.blank?
60
+ redirect_to send("show_page#{multi_language? ? '_with_language' : '' }_path", :urlname => @page.urlname, :lang => multi_language? ? @page.language_code : nil)
61
+ end
62
+
63
+ def create#:nodoc:
64
+ @message = Message.new(params[:mail])
65
+ @message.ip = request.remote_ip
66
+ element = Element.find_by_id(@message.contact_form_id)
67
+ @page = element.page
68
+ @root_page = @page.get_language_root
69
+ if @message.save
70
+ if params[:mail_to].blank?
71
+ mail_to = element.ingredient("mail_to")
72
+ else
73
+ mail_to = Alchemy::Config.get(:mailer)[:mail_addresses].detect{ |c| c[0] == params[:mail_to] }[1]
74
+ end
75
+ mail_from = element.ingredient("mail_from") rescue configuration(:mailer)[:mail_from]
76
+ subject = element.ingredient("subject") rescue configuration(:mailer)[:subject]
77
+
78
+ Messages.mail(@message, mail_to, mail_from, subject).deliver
79
+
80
+ if element.ingredient("success_page")
81
+ if multi_language?
82
+ language = Language.find(session[:language_id])
83
+ redirect_to show_page_with_language_url(:urlname => element.ingredient("success_page"), :lang => language.code)
84
+ else
85
+ redirect_to show_page_url(:urlname => element.ingredient("success_page"))
86
+ end
87
+ elsif configuration(:mailer)[:forward_to_page] && configuration(:mailer)[:mail_success_page]
88
+ redirect_to :controller => 'pages', :action => 'show', :urlname => Page.find_by_urlname(configuration(:mailer)[:mail_success_page]).urlname
89
+ else
90
+ flash[:notice] = I18n.t('alchemy.contactform.messages.success')
91
+ redirect_to :controller => 'pages', :action => 'show', :urlname => Page.language_root_for(session[:language_id]).urlname
92
+ end
93
+ else
94
+ render :template => '/pages/show', :layout => 'pages'
95
+ end
96
+ end
97
+
98
+ end
@@ -0,0 +1,137 @@
1
+ class PagesController < AlchemyController
2
+
3
+ unloadable
4
+
5
+ before_filter :set_language_from_client, :only => [:show, :sitemap]
6
+ before_filter :get_page_from_urlname, :only => [:show, :sitemap]
7
+
8
+ filter_access_to :show, :attribute_check => true
9
+
10
+ caches_action(
11
+ :show,
12
+ :layout => false,
13
+ :cache_path => Proc.new { |c| c.multi_language? ? "#{session[:language_code]}/#{c.params[:urlname]}" : "#{c.params[:urlname]}" },
14
+ :if => Proc.new { |c|
15
+ if Alchemy::Config.get(:cache_pages)
16
+ page = Page.find_by_urlname_and_language_id_and_public(
17
+ c.params[:urlname],
18
+ session[:language_id],
19
+ true,
20
+ :select => 'page_layout, language_id, urlname'
21
+ )
22
+ if page
23
+ pagelayout = Alchemy::PageLayout.get(page.page_layout)
24
+ pagelayout['cache'].nil? || pagelayout['cache']
25
+ end
26
+ else
27
+ false
28
+ end
29
+ }
30
+ )
31
+
32
+ # Showing page from params[:urlname]
33
+ # @page is fetched via before filter
34
+ # @root_page is fetched via before filter
35
+ # @language fetched via before_filter in alchemy_controller
36
+ # rendering page and querying for search results if any query is present
37
+ def show
38
+ if configuration(:ferret) && !params[:query].blank?
39
+ perform_search
40
+ end
41
+ render :layout => params[:layout].blank? ? 'pages' : params[:layout] == 'none' ? false : params[:layout]
42
+ end
43
+
44
+ # Renders a Google conform sitemap in xml
45
+ def sitemap
46
+ @pages = Page.find_all_by_sitemap_and_public(true, true)
47
+ respond_to do |format|
48
+ format.xml { render :layout => "sitemap" }
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def get_page_from_urlname
55
+ if params[:urlname].blank?
56
+ @page = Page.language_root_for(session[:language_id])
57
+ else
58
+ @page = Page.find_by_urlname_and_language_id(params[:urlname], session[:language_id])
59
+ end
60
+ if User.admins.count == 0 && @page.nil?
61
+ redirect_to signup_path
62
+ elsif @page.blank?
63
+ render(:file => "#{Rails.root}/public/404.html", :status => 404, :layout => false)
64
+ elsif multi_language? && params[:lang].blank?
65
+ redirect_to show_page_with_language_path(:urlname => @page.urlname, :lang => session[:language_code]), :status => 301
66
+ elsif multi_language? && params[:urlname].blank? && !params[:lang].blank?
67
+ redirect_to show_page_with_language_path(:urlname => @page.urlname, :lang => params[:lang]), :status => 301
68
+ elsif configuration(:redirect_to_public_child) && !@page.public?
69
+ redirect_to_public_child
70
+ elsif !multi_language? && !params[:lang].blank?
71
+ redirect_to show_page_path(:urlname => @page.urlname), :status => 301
72
+ elsif @page.has_controller?
73
+ redirect_to(@page.controller_and_action)
74
+ else
75
+ if params[:urlname].blank?
76
+ @root_page = @page
77
+ else
78
+ @root_page = Page.language_root_for(session[:language_id])
79
+ end
80
+ end
81
+ end
82
+
83
+ def perform_search
84
+ @rtf_search_results = EssenceRichtext.find_with_ferret(
85
+ "*" + params[:query] + "*",
86
+ {:limit => :all},
87
+ {:conditions => "public = 1"}
88
+ )
89
+ @text_search_results = EssenceText.find_with_ferret(
90
+ "*" + params[:query] + "*",
91
+ {:limit => :all},
92
+ {:conditions => "public = 1"}
93
+ )
94
+ end
95
+
96
+ def find_first_public(page)
97
+ if(page.public == true)
98
+ return page
99
+ end
100
+ page.children.each do |child|
101
+ result = find_first_public(child)
102
+ if(result!=nil)
103
+ return result
104
+ end
105
+ end
106
+ return nil
107
+ end
108
+
109
+ def redirect_to_public_child
110
+ @page = find_first_public(@page)
111
+ if @page.blank?
112
+ render :file => "#{Rails.root}/public/404.html", :status => 404, :layout => false
113
+ else
114
+ redirect_page
115
+ end
116
+ end
117
+
118
+ def redirect_page
119
+ get_additional_params
120
+ redirect_to(
121
+ send(
122
+ "show_page_#{multi_language? ? 'with_language_' : nil }path".to_sym, {
123
+ :lang => (multi_language? ? @page.language_code : nil),
124
+ :urlname => @page.urlname
125
+ }.merge(@additional_params)
126
+ ),
127
+ :status => 301
128
+ )
129
+ end
130
+
131
+ def get_additional_params
132
+ @additional_params = params.clone.delete_if do |key, value|
133
+ ["action", "controller", "urlname", "lang"].include?(key)
134
+ end
135
+ end
136
+
137
+ end
@@ -0,0 +1,68 @@
1
+ class PicturesController < AlchemyController
2
+
3
+ unloadable
4
+
5
+ caches_page :show, :thumbnail, :zoom
6
+
7
+ filter_access_to :thumbnail
8
+
9
+ def show
10
+ @picture = Picture.find(params[:id])
11
+ @size = params[:size]
12
+ @crop = !params[:crop].nil?
13
+ @crop_from = normalized_size(params[:crop_from])
14
+ @crop_size = params[:crop_size]
15
+ @padding = params[:padding]
16
+ @upsample = !params[:upsample].nil? ? true : false
17
+ @effects = params[:effects]
18
+ respond_to do |format|
19
+ format.jpg
20
+ format.png
21
+ format.gif
22
+ end
23
+ end
24
+
25
+ def thumbnail
26
+ @picture = Picture.find(params[:id])
27
+ case params[:size]
28
+ when "small"
29
+ then
30
+ @size = "80x60"
31
+ when "medium"
32
+ then
33
+ @size = "160x120"
34
+ when "large"
35
+ then
36
+ @size = "240x180"
37
+ when nil
38
+ @size = "111x93"
39
+ else
40
+ @size = params[:size]
41
+ end
42
+ if !params[:crop_size].blank? && !params[:crop_from].blank?
43
+ @crop = true
44
+ elsif params[:crop] == 'crop'
45
+ @default_crop = true
46
+ end
47
+ respond_to do |format|
48
+ format.png
49
+ end
50
+ end
51
+
52
+ def zoom
53
+ @picture = Picture.find(params[:id])
54
+ respond_to do |format|
55
+ format.png
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def normalized_size(size)
62
+ return "" if size.blank?
63
+ size.split("x").map do |s|
64
+ s.to_i < 0 ? 0 : s.to_i
65
+ end.join('x')
66
+ end
67
+
68
+ end
@@ -0,0 +1,7 @@
1
+ module Admin::AttachmentsHelper
2
+
3
+ def mime_to_human mime
4
+ I18n.t("alchemy.mime_types.#{mime}", :default => _('document'))
5
+ end
6
+
7
+ end
@@ -0,0 +1,28 @@
1
+ module Admin::ElementsHelper
2
+
3
+ # Returns an Array for essence_text_editor select options_for_select.
4
+ def elements_by_name_for_select(name, options={})
5
+ defaults = {
6
+ :grouped_by_page => true,
7
+ :from_page => :all
8
+ }
9
+ options = defaults.merge(options)
10
+ elements = all_elements_by_name(
11
+ name,
12
+ :from_page => options[:from_page]
13
+ )
14
+ if options[:grouped_by_page] && options[:from_page] == :all
15
+ elements_for_options = {}
16
+ pages = elements.collect(&:page).compact.uniq
17
+ pages.sort{ |x,y| x.name <=> y.name }.each do |page|
18
+ page_elements = page.elements.select { |e| e.name == name }
19
+ elements_for_options[page.name] = page_elements.map { |pe| [pe.preview_text, pe.id.to_s] }
20
+ end
21
+ else
22
+ elements_for_options = elements.map { |e| [e.preview_text, e.id.to_s] }
23
+ elements_for_options = [''] + elements_for_options
24
+ end
25
+ return elements_for_options
26
+ end
27
+
28
+ end
@@ -0,0 +1,3 @@
1
+ module Admin::PagesHelper
2
+
3
+ end
@@ -0,0 +1,26 @@
1
+ module Admin::PicturesHelper
2
+
3
+ def create_or_assign_url(picture_to_assign, options)
4
+ if @content.nil?
5
+ {
6
+ :controller => :contents,
7
+ :action => :create,
8
+ :picture_id => picture_to_assign.id,
9
+ :content => {
10
+ :essence_type => "EssencePicture",
11
+ :element_id => @element.id
12
+ },
13
+ :options => options
14
+ }
15
+ else
16
+ {
17
+ :controller => :essence_pictures,
18
+ :action => :assign,
19
+ :picture_id => picture_to_assign.id,
20
+ :id => @content.id,
21
+ :options => options
22
+ }
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,1168 @@
1
+ # All methods (helpers) in this helper are used by Alchemy to render elements, contents and layouts on the Page.
2
+ #
3
+ # TODO: list all important infos here.
4
+ #
5
+ # Most Important Infos:
6
+ # ---
7
+ #
8
+ # 1. The most important helpers for webdevelopers are the render_navigation(), render_elements() and the render_page_layout() helpers.
9
+ # 2. The currently displayed page can be accessed via the @page variable.
10
+ # 3. All important meta data from @page will be rendered via the render_meta_data() helper.
11
+
12
+ module AlchemyHelper
13
+
14
+ include FastGettext::Translation
15
+
16
+ def configuration(name)
17
+ return Alchemy::Config.get(name)
18
+ end
19
+
20
+ # An alias for truncate.
21
+ # Left here for downwards compatibilty.
22
+ def shorten(text, length)
23
+ text.truncate(:length => length)
24
+ end
25
+
26
+ def render_editor(element)
27
+ render_element(element, :editor)
28
+ end
29
+
30
+ def get_content(element, position)
31
+ return element.contents[position - 1]
32
+ end
33
+
34
+ # Renders all elements from @page.
35
+ # ---
36
+ # == Options are:
37
+ # :only => [] A list of element names to be rendered only. Very usefull if you want to render a specific element type in a special html part (e.g.. <div>) of your page and all other elements in another part.
38
+ # :except => [] A list of element names to be rendered. The opposite of the only option.
39
+ # :from_page The Page.page_layout string from which the elements are rendered from, or you even pass a Page object.
40
+ # :count The amount of elements to be rendered (beginns with first element found)
41
+ # :fallback => {:for => 'ELEMENT_NAME', :with => 'ELEMENT_NAME', :from => 'PAGE_LAYOUT'} when no element from this name is found on page, then use this element from that page
42
+ # :sort_by => Content#name A Content name to sort the elements by
43
+ # :reverse => boolean Reverse the rendering order
44
+ #
45
+ # This helper also stores all pages where elements gets rendered on, so we can sweep them later if caching expires!
46
+ #
47
+ def render_elements(options = {})
48
+ default_options = {
49
+ :except => [],
50
+ :only => [],
51
+ :from_page => "",
52
+ :count => nil,
53
+ :offset => nil,
54
+ :locals => {},
55
+ :render_format => "html",
56
+ :fallback => nil
57
+ }
58
+ options = default_options.merge(options)
59
+ if options[:from_page].blank?
60
+ page = @page
61
+ else
62
+ if options[:from_page].class == Page
63
+ page = options[:from_page]
64
+ else
65
+ page = Page.find_all_by_page_layout_and_language_id(options[:from_page], session[:language_id])
66
+ end
67
+ end
68
+ if page.blank?
69
+ warning('Page is nil')
70
+ return ""
71
+ else
72
+ show_non_public = configuration(:cache_pages) ? false : defined?(current_user)
73
+ if page.class == Array
74
+ all_elements = page.collect { |p| p.find_elements(options, show_non_public) }.flatten
75
+ else
76
+ all_elements = page.find_elements(options, show_non_public)
77
+ end
78
+ unless options[:sort_by].blank?
79
+ all_elements = all_elements.sort_by { |e| e.contents.detect { |c| c.name == options[:sort_by] }.ingredient }
80
+ end
81
+ all_elements.reverse! if options[:reverse_sort] || options[:reverse]
82
+ element_string = ""
83
+ if options[:fallback]
84
+ unless all_elements.detect { |e| e.name == options[:fallback][:for] }
85
+ if from = Page.find_by_page_layout(options[:fallback][:from])
86
+ all_elements += from.elements.find_all_by_name(options[:fallback][:with].blank? ? options[:fallback][:for] : options[:fallback][:with])
87
+ end
88
+ end
89
+ end
90
+ all_elements.each_with_index do |element, i|
91
+ element_string += render_element(element, :view, options, i+1)
92
+ end
93
+ element_string.html_safe
94
+ end
95
+ end
96
+
97
+ # This helper renders the Element partial for either the view or the editor part.
98
+ # Generate element partials with ./script/generate elements
99
+ def render_element(element, part = :view, options = {}, i = 1)
100
+ begin
101
+ if element.blank?
102
+ warning('Element is nil')
103
+ render :partial => "elements/#{part}_not_found", :locals => {:name => 'nil'}
104
+ else
105
+ default_options = {
106
+ :shorten_to => nil,
107
+ :render_format => "html"
108
+ }
109
+ options = default_options.merge(options)
110
+ element.store_page(@page) if part == :view
111
+ path1 = "#{Rails.root}/app/views/elements/"
112
+ path2 = "#{Rails.root}/vendor/plugins/alchemy/app/views/elements/"
113
+ partial_name = "_#{element.name.underscore}_#{part}.html.erb"
114
+ locals = options.delete(:locals)
115
+ render(
116
+ :partial => "elements/#{element.name.underscore}_#{part}.#{options[:render_format]}.erb",
117
+ :locals => {
118
+ :element => element,
119
+ :options => options,
120
+ :counter => i
121
+ }.merge(locals || {})
122
+ )
123
+ end
124
+ rescue ActionView::MissingTemplate
125
+ warning(%(
126
+ Element #{part} partial not found for #{element.name}.\n
127
+ Looking for #{partial_name}, but not found
128
+ neither in #{path1}
129
+ nor in #{path2}
130
+ Use ./script/generate elements to generate them.
131
+ Maybe you still have old style partial names? (like .rhtml). Then please rename them in .html.erb'
132
+ ))
133
+ render :partial => "elements/#{part}_not_found", :locals => {:name => element.name, :error => "Element #{part} partial not found. Use ./script/generate elements to generate them."}
134
+ end
135
+ end
136
+
137
+ # Renders the Content partial that is given (:editor, or :view).
138
+ # You can pass several options that are used by the different contents.
139
+ #
140
+ # For the view partial:
141
+ # :image_size => "111x93" Used by EssencePicture to render the image via RMagick to that size.
142
+ # :css_class => "" This css class gets attached to the content view.
143
+ # :date_format => "Am %d. %m. %Y, um %H:%Mh" Espacially fot the EssenceDate. See Date.strftime for date formatting.
144
+ # :caption => true Pass true to enable that the EssencePicture.caption value gets rendered.
145
+ # :blank_value => "" Pass a String that gets rendered if the content.essence is blank.
146
+ #
147
+ # For the editor partial:
148
+ # :css_class => "" This css class gets attached to the content editor.
149
+ # :last_image_deletable => false Pass true to enable that the last image of an imagecollection (e.g. image gallery) is deletable.
150
+ def render_essence(content, part = :view, options = {}, html_options = {})
151
+ if content.nil?
152
+ return part == :view ? "" : warning('Content is nil', _("content_not_found"))
153
+ elsif content.essence.nil?
154
+ return part == :view ? "" : warning('Essence is nil', _("content_essence_not_found"))
155
+ end
156
+ defaults = {
157
+ :for_editor => {
158
+ :as => 'text_field',
159
+ :css_class => 'long',
160
+ :render_format => "html"
161
+ },
162
+ :for_view => {
163
+ :image_size => "120x90",
164
+ :css_class => "",
165
+ :date_format => "%d. %m. %Y, %H:%Mh",
166
+ :caption => true,
167
+ :blank_value => "",
168
+ :render_format => "html"
169
+ }
170
+ }
171
+ options_for_partial = defaults[('for_' + part.to_s).to_sym].merge(options[('for_' + part.to_s).to_sym])
172
+ options = options.merge(defaults)
173
+ render(
174
+ :partial => "essences/#{content.essence.class.name.underscore}_#{part.to_s}.#{options_for_partial[:render_format]}.erb",
175
+ :locals => {
176
+ :content => content,
177
+ :options => options_for_partial,
178
+ :html_options => html_options
179
+ }
180
+ )
181
+ end
182
+
183
+ # Renders the Content editor partial from the given Content.
184
+ # For options see -> render_essence
185
+ def render_essence_editor(content, options = {})
186
+ render_essence(content, :editor, :for_editor => options)
187
+ end
188
+
189
+ # Renders the Content view partial from the given Content.
190
+ # For options see -> render_essence
191
+ def render_essence_view(content, options = {}, html_options = {})
192
+ render_essence(content, :view, {:for_view => options}, html_options)
193
+ end
194
+
195
+ # Renders the Content editor partial from essence_type.
196
+ #
197
+ # Options are:
198
+ # * element (Element) - the Element the contents are in (obligatory)
199
+ # * type (String) - the type of Essence (obligatory)
200
+ # * options (Hash):
201
+ # ** :position (Integer) - The position of the Content inside the Element. I.E. for getting the n-th EssencePicture. Default is 1 (the first)
202
+ # ** :all (String) - Pass :all to get all Contents of that name. Default false
203
+ # * editor_options (Hash) - Will be passed to the render_essence_editor partial renderer
204
+ #
205
+ def render_essence_editor_by_type(element, essence_type, options = {}, editor_options = {})
206
+ return warning('Element is nil', _("no_element_given")) if element.blank?
207
+ return warning('EssenceType is blank', _("No EssenceType given")) if essence_type.blank?
208
+ defaults = {
209
+ :position => 1,
210
+ :all => false
211
+ }
212
+ options = defaults.merge(options)
213
+ return_string = ""
214
+ if options[:all]
215
+ contents = element.contents.find_all_by_essence_type_and_name(essence_type, options[:all])
216
+ contents.each do |content|
217
+ return_string << render_essence(content, :editor, :for_editor => editor_options)
218
+ end
219
+ else
220
+ content = element.contents.find_by_essence_type_and_position(essence_type, options[:position])
221
+ return_string = render_essence(content, :editor, :for_editor => editor_options)
222
+ end
223
+ return_string
224
+ end
225
+
226
+ # Renders the Content view partial from the given Element for the essence_type (e.g. EssenceRichtext).
227
+ # For multiple contents of same kind inside one molecue just pass a position so that will be rendered.
228
+ # Otherwise the first content found for this type will be rendered.
229
+ # For options see -> render_essence
230
+ def render_essence_view_by_type(element, type, position, options = {}, html_options = {})
231
+ if element.blank?
232
+ warning('Element is nil')
233
+ return ""
234
+ end
235
+ if position.nil?
236
+ content = element.content_by_type(type)
237
+ else
238
+ content = element.contents.find_by_essence_type_and_position(type, position)
239
+ end
240
+ render_essence(content, :view, :for_view => options)
241
+ end
242
+
243
+ # Renders the Content view partial from the given Element by position (e.g. 1).
244
+ # For options see -> render_essence
245
+ def render_essence_view_by_position(element, position, options = {}, html_options = {})
246
+ if element.blank?
247
+ warning('Element is nil')
248
+ return ""
249
+ end
250
+ content = element.contents.find_by_position(position)
251
+ render_essence(content, :view, {:for_view => options}, html_options)
252
+ end
253
+
254
+ # Renders the Content editor partial from the given Element by position (e.g. 1).
255
+ # For options see -> render_essence
256
+ def render_essence_editor_by_position(element, position, options = {})
257
+ if element.blank?
258
+ warning('Element is nil')
259
+ return ""
260
+ end
261
+ content = element.contents.find_by_position(position)
262
+ render_essence(content, :editor, :for_editor => options)
263
+ end
264
+
265
+ # Renders the Content editor partial found in views/contents/ for the content with name inside the passed Element.
266
+ # For options see -> render_essence
267
+ #
268
+ # Content creation on the fly:
269
+ #
270
+ # If you update the elements.yml file after creating an element this helper displays a error message with an option to create the content.
271
+ #
272
+ def render_essence_editor_by_name(element, name, options = {})
273
+ if element.blank?
274
+ return warning('Element is nil', _("no_element_given"))
275
+ end
276
+ content = element.content_by_name(name)
277
+ if content.blank?
278
+ render :partial => 'admin/contents/missing', :locals => {:element => element, :name => name}
279
+ else
280
+ render_essence(content, :editor, :for_editor => options)
281
+ end
282
+ end
283
+
284
+ # Renders the Content view partial from the passed Element for passed content name.
285
+ # For options see -> render_essence
286
+ def render_essence_view_by_name(element, name, options = {}, html_options = {})
287
+ if element.blank?
288
+ warning('Element is nil')
289
+ return ""
290
+ end
291
+ content = element.content_by_name(name)
292
+ render_essence(content, :view, {:for_view => options}, html_options)
293
+ end
294
+
295
+ # Renders the name of elements content or the default name defined in elements.yml
296
+ def render_content_name(content)
297
+ if content.blank?
298
+ warning('Element is nil')
299
+ return ""
300
+ else
301
+ content_name = content.name_for_label
302
+ end
303
+ if content.description.blank?
304
+ warning("Content #{content.name} is missing its description")
305
+ title = _("Warning: Content '%{contentname}' is missing its description.") % {:contentname => content.name}
306
+ content_name = %(<span class="warning icon" title="#{title}"></span>&nbsp;) + content_name
307
+ end
308
+ content.has_validations? ? "#{content_name}<span class='validation_indicator'>*</span>" : content_name
309
+ end
310
+
311
+ # Returns @page.title
312
+ #
313
+ # The options are:
314
+ # :prefix => ""
315
+ # :seperator => "|"
316
+ #
317
+ # == Webdevelopers:
318
+ # Please use the render_meta_data() helper. There all important meta information gets rendered in one helper.
319
+ # So you dont have to worry about anything.
320
+ def render_page_title options={}
321
+ default_options = {
322
+ :prefix => "",
323
+ :seperator => "|"
324
+ }
325
+ default_options.update(options)
326
+ unless @page.title.blank?
327
+ h("#{default_options[:prefix]} #{default_options[:seperator]} #{@page.title}")
328
+ else
329
+ h("")
330
+ end
331
+ end
332
+
333
+ # Returns a complete html <title> tag for the <head> part of the html document.
334
+ #
335
+ # == Webdevelopers:
336
+ # Please use the render_meta_data() helper. There all important meta information gets rendered in one helper.
337
+ # So you dont have to worry about anything.
338
+ def render_title_tag options={}
339
+ default_options = {
340
+ :prefix => "",
341
+ :seperator => "|"
342
+ }
343
+ options = default_options.merge(options)
344
+ title = render_page_title(options)
345
+ %(<title>#{title}</title>).html_safe
346
+ end
347
+
348
+ # Renders a html <meta> tag for :name => "" and :content => ""
349
+ #
350
+ # == Webdevelopers:
351
+ # Please use the render_meta_data() helper. There all important meta information gets rendered in one helper.
352
+ # So you dont have to worry about anything.
353
+ def render_meta_tag(options={})
354
+ default_options = {
355
+ :name => "",
356
+ :default_language => "de",
357
+ :content => ""
358
+ }
359
+ options = default_options.merge(options)
360
+ lang = (@page.language.blank? ? options[:default_language] : @page.language.code)
361
+ %(<meta name="#{options[:name]}" content="#{options[:content]}" lang="#{lang}" />).html_safe
362
+ end
363
+
364
+ # Renders a html <meta http-equiv="Content-Language" content="#{lang}" /> for @page.language.
365
+ #
366
+ # == Webdevelopers:
367
+ # Please use the render_meta_data() helper. There all important meta information gets rendered in one helper.
368
+ # So you dont have to worry about anything.
369
+ def render_meta_content_language_tag(options={})
370
+ default_options = {
371
+ :default_language => "de"
372
+ }
373
+ options = default_options.merge(options)
374
+ lang = (@page.language_code.blank? ? options[:default_language] : @page.language_code)
375
+ %(<meta http-equiv="Content-Language" content="#{lang}" />).html_safe
376
+ end
377
+
378
+ # = This helper takes care of all important meta tags for your @page.
379
+ # ---
380
+ # The meta data is been taken from the @page.title, @page.meta_description, @page.meta_keywords, @page.updated_at and @page.language database entries managed by the Alchemy user via the Alchemy cockpit.
381
+ #
382
+ # Assume that the user has entered following data into the Alchemy cockpit of the Page "home" and that the user wants that the searchengine (aka. google) robot should index the page and should follow all links on this page:
383
+ #
384
+ # Title = Homepage
385
+ # Description = Your page description
386
+ # Keywords: cms, ruby, rubyonrails, rails, software, development, html, javascript, ajax
387
+ #
388
+ # Then placing render_meta_data(:title_prefix => "company", :title_seperator => "::") into the <head> part of the pages.html.erb layout produces:
389
+ #
390
+ # <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
391
+ # <meta http-equiv="Content-Language" content="de" />
392
+ # <title>Company :: #{@page.title}</title>
393
+ # <meta name="description" content="Your page description" />
394
+ # <meta name="keywords" content="cms, ruby, rubyonrails, rails, software, development, html, javascript, ajax" />
395
+ # <meta name="generator" content="Alchemy VERSION" />
396
+ # <meta name="date" content="Tue Dec 16 10:21:26 +0100 2008" />
397
+ # <meta name="robots" content="index, follow" />
398
+ #
399
+ def render_meta_data options={}
400
+ if @page.blank?
401
+ warning("No Page found!")
402
+ return nil
403
+ end
404
+ default_options = {
405
+ :title_prefix => "",
406
+ :title_seperator => "|",
407
+ :default_lang => "de"
408
+ }
409
+ options = default_options.merge(options)
410
+ #render meta description of the root page from language if the current meta description is empty
411
+ if @page.meta_description.blank?
412
+ description = Page.find_by_language_root_and_language_id(true, session[:language_id]).meta_description rescue ""
413
+ else
414
+ description = @page.meta_description
415
+ end
416
+ #render meta keywords of the root page from language if the current meta keywords is empty
417
+ if @page.meta_keywords.blank?
418
+ keywords = Page.find_by_language_root_and_language_id(true, session[:language_id]).meta_keywords rescue ""
419
+ else
420
+ keywords = @page.meta_keywords
421
+ end
422
+ robot = "#{@page.robot_index? ? "" : "no"}index, #{@page.robot_follow? ? "" : "no"}follow"
423
+ meta_string = %(
424
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
425
+ #{render_meta_content_language_tag}
426
+ #{render_title_tag( :prefix => options[:title_prefix], :seperator => options[:title_seperator])}
427
+ #{render_meta_tag( :name => "description", :content => description)}
428
+ #{render_meta_tag( :name => "keywords", :content => keywords)}
429
+ <meta name="generator" content="Alchemy #{Alchemy::VERSION}" />
430
+ <meta name="date" content="#{@page.updated_at}" />
431
+ <meta name="robots" content="#{robot}" />
432
+ )
433
+ if @page.contains_feed?
434
+ meta_string += %(
435
+ <link rel="alternate" type="application/rss+xml" title="RSS" href="#{multi_language? ? show_page_with_language_url(:protocol => 'feed', :urlname => @page.urlname, :lang => @page.language_code, :format => :rss) : show_page_url(:protocol => 'feed', :urlname => @page.urlname, :format => :rss)}" />
436
+ )
437
+ end
438
+ return meta_string.html_safe
439
+ end
440
+
441
+ # Returns an array of all pages in the same branch from current. Used internally to find the active page in navigations.
442
+ def breadcrumb(current)
443
+ return [] if current.nil?
444
+ result = Array.new
445
+ result << current
446
+ while current = current.parent
447
+ result << current
448
+ end
449
+ return result.reverse
450
+ end
451
+
452
+ # Returns a html string for a linked breadcrumb from root to current page.
453
+ # == Options:
454
+ # :seperator => %(<span class="seperator">></span>) Maybe you don't want this seperator. Pass another one.
455
+ # :page => @page Pass a different Page instead of the default (@page).
456
+ # :without => nil Pass Pageobject or array of Pages that must not be displayed.
457
+ # :public_only => false Pass boolean for displaying hidden pages only.
458
+ # :visible_only => true Pass boolean for displaying (in navigation) visible pages only.
459
+ # :restricted_only => false Pass boolean for displaying restricted pages only.
460
+ # :reverse => false Pass boolean for displaying reversed breadcrumb.
461
+ def render_breadcrumb(options={})
462
+ default_options = {
463
+ :seperator => %(<span class="seperator">&gt;</span>),
464
+ :page => @page,
465
+ :without => nil,
466
+ :public_only => false,
467
+ :visible_only => true,
468
+ :restricted_only => false,
469
+ :reverse => false
470
+ }
471
+ options = default_options.merge(options)
472
+ pages = breadcrumb(options[:page])
473
+ pages.delete(Page.root)
474
+ unless options[:without].nil?
475
+ unless options[:without].class == Array
476
+ pages.delete(options[:without])
477
+ else
478
+ pages = pages - options[:without]
479
+ end
480
+ end
481
+ if(options[:visible_only])
482
+ pages.reject!{|p| !p.visible? }
483
+ end
484
+ if(options[:public_only])
485
+ pages.reject!{|p| !p.public? }
486
+ end
487
+ if(options[:restricted_only])
488
+ pages.reject!{|p| !p.restricted? }
489
+ end
490
+ if(options[:reverse])
491
+ pages.reverse!
492
+ end
493
+ bc = []
494
+ pages.each do |page|
495
+ urlname = page.urlname
496
+ (page.name == @page.name) ? css_class = "active" : nil
497
+ if page == pages.last
498
+ css_class.blank? ? css_class = "last" : css_class = [css_class, "last"].join(" ")
499
+ elsif page == pages.first
500
+ css_class.blank? ? css_class = "first" : css_class = [css_class, "last"].join(" ")
501
+ end
502
+ if multi_language?
503
+ url = show_page_with_language_url(:urlname => urlname, :lang => page.language_code)
504
+ else
505
+ url = show_page_url(:urlname => urlname)
506
+ end
507
+ bc << link_to( h(page.name), url, :class => css_class, :title => page.title )
508
+ end
509
+ bc.join(options[:seperator]).html_safe
510
+ end
511
+
512
+ # returns true if page is in the active branch
513
+ def page_active? page
514
+ @breadcrumb ||= breadcrumb(@page)
515
+ @breadcrumb.include? page
516
+ end
517
+
518
+ # = This helper renders the navigation.
519
+ #
520
+ # It produces a html <ul><li></li></ul> structure with all necessary classes and ids so you can produce nearly every navigation the web uses today.
521
+ # E.G. dropdown-navigations, simple mainnavigations or even complex nested ones.
522
+ # ---
523
+ # == En detail:
524
+ #
525
+ # <ul>
526
+ # <li class="first" id="home"><a href="home" class="active">Homepage</a></li>
527
+ # <li id="contact"><a href="contact">Contact</a></li>
528
+ # <li class="last" id="imprint"><a href="imprint">Imprint</a></li>
529
+ # </ul>
530
+ #
531
+ # As you can see: Everything you need.
532
+ #
533
+ # Not pleased with the way Alchemy produces the navigation structure?
534
+ # Then feel free to overwrite the partials (_navigation_renderer.html.erb and _navigation_link.html.erb) found in views/pages/partials/ or pass different partials via the options :navigation_partial and :navigation_link_partial.
535
+ #
536
+ # == The options are:
537
+ #
538
+ # :submenu => false Do you want a nested <ul> <li> structure for the deeper levels of your navigation, or not? Used to display the subnavigation within the mainnaviagtion. E.g. for dropdown menues.
539
+ # :from_page => @root_page Do you want to render a navigation from a different page then the current page? Then pass an Page instance or a Alchemy::PageLayout name as string.
540
+ # :spacer => "" Yeah even a spacer for the entries can be passed. Simple string, or even a complex html structure. E.g: "<span class='spacer'>|</spacer>". Only your imagination is the limit. And the W3C of course :)
541
+ # :navigation_partial => "navigation_renderer" Pass a different partial to be taken for the navigation rendering. CAUTION: Only for the advanced Alchemy webdevelopers. The standard partial takes care of nearly everything. But maybe you are an adventures one ^_^
542
+ # :navigation_link_partial => "navigation_link" Alchemy places an <a> html link in <li> tags. The tag automatically has an active css class if necessary. So styling is everything. But maybe you don't want this. So feel free to make you own partial and pass the filename here.
543
+ # :show_nonactive => false Commonly Alchemy only displays the submenu of the active page (if :submenu => true). If you want to display all child pages then pass true (together with :submenu => true of course). E.g. for the popular css-driven dropdownmenues these days.
544
+ # :show_title => true For our beloved SEOs :). Appends a title attribute to all links and places the page.title content into it.
545
+ def render_navigation(options = {})
546
+ default_options = {
547
+ :submenu => false,
548
+ :all_sub_menues => false,
549
+ :from_page => @root_page,
550
+ :spacer => "",
551
+ :navigation_partial => "partials/navigation_renderer",
552
+ :navigation_link_partial => "partials/navigation_link",
553
+ :show_nonactive => false,
554
+ :restricted_only => nil,
555
+ :show_title => true,
556
+ :reverse => false,
557
+ :reverse_children => false
558
+ }
559
+ options = default_options.merge(options)
560
+ if options[:from_page].is_a?(String)
561
+ page = Page.find_by_page_layout_and_language_id(options[:from_page], session[:language_id])
562
+ else
563
+ page = options[:from_page]
564
+ end
565
+ if page.blank?
566
+ warning("No Page found for #{options[:from_page]}")
567
+ return ""
568
+ end
569
+ conditions = {
570
+ :parent_id => page.id,
571
+ :restricted => options[:restricted_only] || false,
572
+ :visible => true
573
+ }
574
+ if options[:restricted_only].nil?
575
+ conditions.delete(:restricted)
576
+ end
577
+ pages = Page.where(conditions).order("lft ASC")
578
+ if options[:reverse]
579
+ pages.reverse!
580
+ end
581
+ render :partial => options[:navigation_partial], :locals => {:options => options, :pages => pages}
582
+ end
583
+
584
+ # Renders the children of the given page (standard is the current page), the given page and its siblings if there are no children, or it renders just nil.
585
+ # Use this helper if you want to render the subnavigation independent from the mainnavigation. E.g. to place it in a different layer on your website.
586
+ # If :from_page's level in the site-hierarchy is greater than :level (standard is 2) and the given page has no children, the returned output will be the :from_page and it's siblings
587
+ # This method will assign all its options to the the render_navigation method, so you are able to assign the same options as to the render_navigation method.
588
+ # Normally there is no need to change the level parameter, just in a few special cases.
589
+ def render_subnavigation(options = {})
590
+ default_options = {
591
+ :from_page => @page,
592
+ :level => 2
593
+ }
594
+ options = default_options.merge(options)
595
+ if !options[:from_page].nil?
596
+ if (options[:from_page].children.blank? && options[:from_page].level > options[:level])
597
+ options = options.merge(:from_page => Page.find(options[:from_page].parent_id))
598
+ end
599
+ render_navigation(options)
600
+ else
601
+ return nil
602
+ end
603
+ end
604
+
605
+ # Returns true if the current_user (The logged-in Alchemy User) has the admin role.
606
+ def is_admin?
607
+ return false if !current_user
608
+ current_user.admin?
609
+ end
610
+
611
+ # This helper renders the link for a protoypejs-window overlay. We use this for our fancy modal overlay windows in the Alchemy cockpit.
612
+ def link_to_overlay_window(content, url, options={}, html_options={})
613
+ default_options = {
614
+ :size => "100x100",
615
+ :resizable => false,
616
+ :modal => true,
617
+ :overflow => false
618
+ }
619
+ options = default_options.merge(options)
620
+ link_to_function(
621
+ content,
622
+ "Alchemy.openWindow(
623
+ \'#{url}\',
624
+ \'#{options[:title]}\',
625
+ \'#{options[:size].split('x')[0].to_s}\',
626
+ \'#{options[:size].split('x')[1].to_s}\',
627
+ #{options[:resizable]},
628
+ #{options[:modal]},
629
+ #{options[:overflow]}
630
+ )",
631
+ html_options
632
+ )
633
+ end
634
+
635
+ # Used for rendering the folder link in Admin::Pages.index sitemap.
636
+ def sitemapFolderLink(page)
637
+ return '' if page.level == 1
638
+ if page.folded?(current_user.id)
639
+ css_class = 'folded'
640
+ title = _('Show childpages')
641
+ else
642
+ css_class = 'collapsed'
643
+ title = _('Hide childpages')
644
+ end
645
+ link_to(
646
+ '',
647
+ fold_admin_page_path(page),
648
+ :remote => true,
649
+ :method => :post,
650
+ :class => "page_folder #{css_class}",
651
+ :title => title,
652
+ :id => "fold_button_#{page.id}"
653
+ )
654
+ end
655
+
656
+ # Renders an image_tag from for an image in public/images folder so it can be cached.
657
+ # *Not really working!*
658
+ def static_image_tag image, options={}
659
+ image_tag url_for(:controller => :images, :action => :show_static, :image => image)
660
+ end
661
+
662
+ # Renders the layout from @page.page_layout. File resists in /app/views/page_layouts/_LAYOUT-NAME.html.erb
663
+ def render_page_layout(options={})
664
+ default_options = {
665
+ :render_format => "html"
666
+ }
667
+ options = default_options.merge(options)
668
+ render :partial => "page_layouts/#{@page.page_layout.downcase}.#{options[:render_format]}.erb"
669
+ rescue ActionView::MissingTemplate
670
+ warning("PageLayout: '#{@page.page_layout}' not found. Rendering standard page_layout.")
671
+ render :partial => "page_layouts/standard"
672
+ end
673
+
674
+ # Returns @current_language set in the action (e.g. Page.show)
675
+ def current_language
676
+ if @current_language.nil?
677
+ warning('@current_language is not set')
678
+ return nil
679
+ else
680
+ @current_language
681
+ end
682
+ end
683
+
684
+ # Returns true if the current page is the root page in the nested set of Pages, false if not.
685
+ def root_page?
686
+ @page == @root_page
687
+ end
688
+
689
+ # Returns the full url containing host, page and anchor for the given element
690
+ def full_url_for_element element
691
+ "http://" + request.env["HTTP_HOST"] + "/" + element.page.urlname + "##{element.name}_#{element.id}"
692
+ end
693
+
694
+ # Used for language selector in Alchemy cockpit sitemap. So the user can select the language branche of the page.
695
+ def language_codes_for_select
696
+ configuration(:languages).collect{ |language|
697
+ language[:language_code]
698
+ }
699
+ end
700
+
701
+ # Used for translations selector in Alchemy cockpit user settings.
702
+ def translations_for_select
703
+ configuration(:translations).collect{ |translation|
704
+ [translation[:language], translation[:language_code]]
705
+ }
706
+ end
707
+
708
+ # Used by Alchemy to display a javascript driven filter for lists in the Alchemy cockpit.
709
+ def js_filter_field options = {}
710
+ default_options = {
711
+ :class => "thin_border js_filter_field",
712
+ :onkeyup => "Alchemy.ListFilter('#contact_list li')",
713
+ :id => "search_field"
714
+ }
715
+ options = default_options.merge(options)
716
+ options[:onkeyup] << ";jQuery('#search_field').val().length >= 1 ? jQuery('.js_filter_field_clear').show() : jQuery('.js_filter_field_clear').hide();"
717
+ filter_field = "<div class=\"js_filter_field_box\">"
718
+ filter_field << text_field_tag("filter", '', options)
719
+ filter_field << content_tag('span', '', :class => 'icon search')
720
+ filter_field << link_to_function(
721
+ "",
722
+ "jQuery('##{options[:id]}').val('');#{options[:onkeyup]}",
723
+ :class => "js_filter_field_clear",
724
+ :style => "display:none",
725
+ :title => _("click_to_show_all")
726
+ )
727
+ filter_field << "<label for=\"search_field\">" + _("search") + "</label>"
728
+ filter_field << "</div>"
729
+ filter_field
730
+ end
731
+
732
+ def clipboard_select_tag(items, html_options = {})
733
+ options = [[_('Please choose'), ""]]
734
+ items.each do |item|
735
+ options << [item.class.to_s == 'Element' ? item.display_name_with_preview_text : item.name, item.id]
736
+ end
737
+ select_tag(
738
+ 'paste_from_clipboard',
739
+ options_for_select(options),
740
+ {
741
+ :class => html_options[:class] || 'very_long',
742
+ :style => html_options[:style]
743
+ }
744
+ )
745
+ end
746
+
747
+ # Returns all elements that could be placed on that page because of the pages layout.
748
+ # The elements are returned as an array to be used in alchemy_selectbox form builder.
749
+ def elements_for_select(elements)
750
+ return [] if elements.nil?
751
+ options = elements.collect{ |e| [I18n.t("alchemy.element_names.#{e['name']}", :default => e['name'].capitalize), e["name"]] }
752
+ return options_for_select(options)
753
+ end
754
+
755
+ # Returns all elements that could be placed on that page because of the pages layout.
756
+ # The elements will be grouped by cell.
757
+ def grouped_elements_for_select(elements)
758
+ return [] if elements.nil?
759
+ cells_definition = Cell.definitions
760
+ return [] if cells_definition.blank?
761
+ options = {}
762
+ celled_elements = []
763
+ cells_definition.each do |cell|
764
+ cell_elements = elements.select { |e| cell['elements'].include?(e['name']) }
765
+ celled_elements += cell_elements
766
+ optgroup_label = Cell.translated_label_for(cell['name'])
767
+ options[optgroup_label] = cell_elements.map { |e| [I18n.t("alchemy.element_names.#{e['name']}", :default => e['name'].capitalize), e['name'] + "##{cell['name']}"] }
768
+ end
769
+ other_elements = elements - celled_elements
770
+ unless other_elements.blank?
771
+ optgroup_label = _('other Elements')
772
+ options[optgroup_label] = other_elements.map { |e| [I18n.t("alchemy.element_names.#{e['name']}", :default => e['name'].capitalize), e['name']] }
773
+ end
774
+ return grouped_options_for_select(options)
775
+ end
776
+
777
+ def link_to_confirmation_window(link_string = "", message = "", url = "", html_options = {})
778
+ title = _("please_confirm")
779
+ ok_lable = _("yes")
780
+ cancel_lable = _("no")
781
+ link_to_function(
782
+ link_string,
783
+ "Alchemy.confirmToDeleteWindow('#{url}', '#{title}', '#{message}', '#{ok_lable}', '#{cancel_lable}');",
784
+ html_options
785
+ )
786
+ end
787
+
788
+ # Renders a form select tag for storing page urlnames
789
+ # Options:
790
+ # * element - element the Content find via content_name to store the pages urlname in.
791
+ # * content_name - the name of the content from element to store the pages urlname in.
792
+ # * options (Hash)
793
+ # ** :only (Hash) - pass page_layout names to :page_layout => [""] so only pages with this page_layout will be displayed inside the select.
794
+ # ** :except (Hash) - pass page_layout names to :page_layout => [""] so all pages except these with this page_layout will be displayed inside the select.
795
+ # ** :page_attribute (Symbol) - The Page attribute which will be stored.
796
+ # * select_options (Hash) - will be passed to the select_tag helper
797
+ def page_selector(element, content_name, options = {}, select_options = {})
798
+ default_options = {
799
+ :except => {
800
+ :page_layout => [""]
801
+ },
802
+ :only => {
803
+ :page_layout => [""]
804
+ },
805
+ :page_attribute => :urlname,
806
+ :prompt => _('Choose page')
807
+ }
808
+ options = default_options.merge(options)
809
+ content = element.content_by_name(content_name)
810
+ if content.nil?
811
+ return warning('Content', _('content_not_found'))
812
+ elsif content.essence.nil?
813
+ return warning('Content', _('content_essence_not_found'))
814
+ end
815
+ pages = Page.where({
816
+ :language_id => session[:language_id],
817
+ :page_layout => options[:only][:page_layout],
818
+ :public => true
819
+ })
820
+ select_tag(
821
+ "contents[content_#{content.id}][body]",
822
+ pages_for_select(pages, content.essence.body, options[:prompt], options[:page_attribute]),
823
+ select_options
824
+ )
825
+ end
826
+
827
+ # Returns an Array build for passing it to the options_for_select helper inside an essence editor partial.
828
+ # Usefull for the select_values options from the render_essence_editor helpers.
829
+ # Options:
830
+ # * :from_page (String, Page) - Return only elements from this page. You can either pass a Page instance, or a page_layout name
831
+ # * :elements_with_name (Array, String) - Return only elements with this name(s).
832
+ def elements_for_essence_editor_select(options={})
833
+ defaults = {
834
+ :from_page => nil,
835
+ :elements_with_name => nil,
836
+ :prompt => _('Please choose')
837
+ }
838
+ options = defaults.merge(options)
839
+ if options[:from_page]
840
+ page = options[:from_page].is_a?(String) ? Page.find_by_page_layout(options[:from_page]) : options[:from_page]
841
+ end
842
+ if page
843
+ elements = options[:elements_with_name].blank? ? page.elements.find_all_by_public(true) : page.elements.find_all_by_public_and_name(true, options[:elements_with_name])
844
+ else
845
+ elements = options[:elements_with_name].blank? ? Element.find_all_by_public(true) : Element.find_all_by_public_and_name(true, options[:elements_with_name])
846
+ end
847
+ select_options = [[options[:prompt], ""]]
848
+ elements.each do |e|
849
+ select_options << [e.display_name_with_preview_text, e.id.to_s]
850
+ end
851
+ select_options
852
+ end
853
+
854
+ # Returns all Pages found in the database as an array for the rails select_tag helper.
855
+ # You can pass a collection of pages to only returns these pages as array.
856
+ # Pass an Page.name or Page.id as second parameter to pass as selected for the options_for_select helper.
857
+ def pages_for_select(pages = nil, selected = nil, prompt = "", page_attribute = :id)
858
+ result = [[prompt.blank? ? _('Choose page') : prompt, ""]]
859
+ if pages.blank?
860
+ pages = Page.find_all_by_language_id_and_public(session[:language_id], true)
861
+ end
862
+ pages.each do |p|
863
+ result << [p.name, p.send(page_attribute).to_s]
864
+ end
865
+ options_for_select(result, selected.to_s)
866
+ end
867
+
868
+ # Returns all public elements found by Element.name.
869
+ # Pass a count to return only an limited amount of elements.
870
+ def all_elements_by_name(name, options = {})
871
+ warning('options[:language] option not allowed any more in all_elements_by_name helper') unless options[:language].blank?
872
+ default_options = {
873
+ :count => :all,
874
+ :from_page => :all
875
+ }
876
+ options = default_options.merge(options)
877
+ if options[:from_page] == :all
878
+ elements = Element.find_all_by_name_and_public(name, true, :limit => options[:count] == :all ? nil : options[:count])
879
+ elsif options[:from_page].class == String
880
+ page = Page.find_by_page_layout_and_language_id(options[:from_page], session[:language_id])
881
+ return [] if page.blank?
882
+ elements = page.elements.find_all_by_name_and_public(name, true, :limit => options[:count] == :all ? nil : options[:count])
883
+ else
884
+ elements = options[:from_page].elements.find_all_by_name_and_public(name, true, :limit => options[:count] == :all ? nil : options[:count])
885
+ end
886
+ end
887
+
888
+ # Returns the public element found by Element.name from the given public Page, either by Page.id or by Page.urlname
889
+ def element_from_page(options = {})
890
+ default_options = {
891
+ :page_urlname => "",
892
+ :page_id => nil,
893
+ :element_name => ""
894
+ }
895
+ options = default_options.merge(options)
896
+ if options[:page_id].blank?
897
+ page = Page.find_by_urlname_and_public(options[:page_urlname], true)
898
+ else
899
+ page = Page.find_by_id_and_public(options[:page_id], true)
900
+ end
901
+ return "" if page.blank?
902
+ element = page.elements.find_by_name_and_public(options[:element_name], true)
903
+ return element
904
+ end
905
+
906
+ # This helper renderes the picture editor for the elements on the Alchemy Desktop.
907
+ # It brings full functionality for adding images to the element, deleting images from it and sorting them via drag'n'drop.
908
+ # Just place this helper inside your element editor view, pass the element as parameter and that's it.
909
+ #
910
+ # Options:
911
+ # :maximum_amount_of_images (integer), default nil. This option let you handle the amount of images your customer can add to this element.
912
+ def render_picture_editor(element, options={})
913
+ default_options = {
914
+ :last_image_deletable => true,
915
+ :maximum_amount_of_images => nil,
916
+ :refresh_sortable => true
917
+ }
918
+ options = default_options.merge(options)
919
+ picture_contents = element.all_contents_by_type("EssencePicture")
920
+ render(
921
+ :partial => "admin/elements/picture_editor",
922
+ :locals => {
923
+ :picture_contents => picture_contents,
924
+ :element => element,
925
+ :options => options
926
+ }
927
+ )
928
+ end
929
+
930
+ def render_essence_selection_editor(element, content, select_options)
931
+ if content.class == String
932
+ content = element.contents.find_by_name(content)
933
+ else
934
+ content = element.contents[content - 1]
935
+ end
936
+ if content.essence.nil?
937
+ return warning('Element', _('content_essence_not_found'))
938
+ end
939
+ select_options = options_for_select(select_options, content.essence.content)
940
+ select_tag(
941
+ "contents[content_#{content.id}]",
942
+ select_options
943
+ )
944
+ end
945
+
946
+ # TOOD: include these via asset_packer yml file
947
+ def stylesheets_from_plugins
948
+ Dir.glob("vendor/plugins/*/assets/stylesheets/*.css").inject("") do |acc, s|
949
+ filename = File.basename(s)
950
+ plugin = s.split("/")[2]
951
+ acc << stylesheet_link_tag("#{plugin}/#{filename}")
952
+ end
953
+ end
954
+
955
+ # TOOD: include these via asset_packer yml file
956
+ def javascripts_from_plugins
957
+ Dir.glob("vendor/plugins/*/assets/javascripts/*.js").inject("") do |acc, s|
958
+ filename = File.basename(s)
959
+ plugin = s.split("/")[2]
960
+ acc << javascript_include_tag("#{plugin}/#{filename}")
961
+ end
962
+ end
963
+
964
+ def admin_main_navigation
965
+ navigation_entries = alchemy_plugins.collect{ |p| p["navigation"] }
966
+ render :partial => 'admin/partials/mainnavigation_entry', :collection => navigation_entries.flatten
967
+ end
968
+
969
+ # Renders the Subnavigation for the admin interface.
970
+ def render_admin_subnavigation(entries)
971
+ render :partial => "admin/partials/sub_navigation", :locals => {:entries => entries}
972
+ end
973
+
974
+ def admin_subnavigation
975
+ plugin = alchemy_plugin(:controller => params[:controller], :action => params[:action])
976
+ unless plugin.nil?
977
+ entries = plugin["navigation"]['sub_navigation']
978
+ render_admin_subnavigation(entries) unless entries.nil?
979
+ else
980
+ ""
981
+ end
982
+ end
983
+
984
+ def admin_mainnavi_active?(mainnav)
985
+ subnavi = mainnav["sub_navigation"]
986
+ nested = mainnav["nested"]
987
+ if !subnavi.blank?
988
+ (!subnavi.detect{ |subnav| subnav["controller"] == params[:controller] && subnav["action"] == params[:action] }.blank?) ||
989
+ (!nested.nil? && !nested.detect{ |n| n["controller"] == params[:controller] && n["action"] == params[:action] }.blank?)
990
+ else
991
+ mainnav["controller"] == params[:controller] && mainnav["action"] == params["action"]
992
+ end
993
+ end
994
+
995
+ # Generates the url for the preview frame.
996
+ # target_url must contain target_controller and target_action.
997
+ def generate_preview_url(target_url)
998
+ preview_url = url_for(
999
+ :controller => ('/' + target_url["target_controller"]),
1000
+ :action => target_url["target_action"],
1001
+ :id => params[:id]
1002
+ )
1003
+ end
1004
+
1005
+ # Returns a string for the id attribute of a html element for the given element
1006
+ def element_dom_id(element)
1007
+ return "" if element.nil?
1008
+ "#{element.name}_#{element.id}"
1009
+ end
1010
+
1011
+ # Returns a string for the id attribute of a html element for the given content
1012
+ def content_dom_id(content)
1013
+ return "" if content.nil?
1014
+ if content.class == String
1015
+ a = Content.find_by_name(content)
1016
+ return "" if a.nil?
1017
+ else
1018
+ a = content
1019
+ end
1020
+ "#{a.essence_type.underscore}_#{a.id}"
1021
+ end
1022
+
1023
+ # Helper for including the nescessary javascripts and stylesheets for the different views.
1024
+ # Together with the rails caching we achieve a good load time.
1025
+ def alchemy_assets_set(setname = 'combined')
1026
+ asset_sets = YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'config/asset_packages.yml'))
1027
+ content_for(:javascript_includes) do
1028
+ js_set = asset_sets['javascripts'].detect { |js| js[setname.to_s] }[setname.to_s]
1029
+ javascript_include_tag(js_set, :cache => 'alchemy/' + setname.to_s)
1030
+ end
1031
+ content_for(:stylesheets) do
1032
+ css_set = asset_sets['stylesheets'].detect { |css| css[setname.to_s] }[setname.to_s]
1033
+ stylesheet_link_tag(css_set, :cache => 'alchemy/' + setname.to_s)
1034
+ end
1035
+ end
1036
+
1037
+ def parse_sitemap_name(page)
1038
+ if multi_language?
1039
+ pathname = "/#{session[:language_code]}/#{page.urlname}"
1040
+ else
1041
+ pathname = "/#{page.urlname}"
1042
+ end
1043
+ pathname
1044
+ end
1045
+
1046
+ def render_new_content_link(element)
1047
+ link_to_overlay_window(
1048
+ _('add new content'),
1049
+ new_admin_element_content_path(element),
1050
+ {
1051
+ :size => '305x40',
1052
+ :title => _('Select an content'),
1053
+ :overflow => true
1054
+ },
1055
+ {
1056
+ :id => "add_content_for_element_#{element.id}",
1057
+ :class => 'button new_content_link'
1058
+ }
1059
+ )
1060
+ end
1061
+
1062
+ def render_create_content_link(element, options = {})
1063
+ defaults = {
1064
+ :label => _('add new content')
1065
+ }
1066
+ options = defaults.merge(options)
1067
+ link_to(
1068
+ options[:label],
1069
+ admin_contents_path(
1070
+ :content => {
1071
+ :name => options[:content_name],
1072
+ :element_id => element.id
1073
+ }
1074
+ ),
1075
+ :method => 'post',
1076
+ :remote => true,
1077
+ :id => "add_content_for_element_#{element.id}",
1078
+ :class => 'button new_content_link'
1079
+ )
1080
+ end
1081
+
1082
+ # Returns an icon
1083
+ def render_icon(icon_class)
1084
+ content_tag('span', '', :class => "icon #{icon_class}")
1085
+ end
1086
+
1087
+ def alchemy_preview_mode_code
1088
+ javascript_include_tag("alchemy/alchemy.preview") if @preview_mode
1089
+ end
1090
+
1091
+ # Renders the data-alchemy-element HTML attribut used for the preview window hover effect.
1092
+ def element_preview_code(element)
1093
+ " data-alchemy-element='#{element.id}'" if @preview_mode && element.page == @page
1094
+ end
1095
+
1096
+ # Logs a message in the Rails logger (warn level) and optionally displays an error message to the user.
1097
+ def warning(message, text = nil)
1098
+ logger.warn %(\n
1099
+ ++++ WARNING: #{message}! from: #{caller.first}\n
1100
+ )
1101
+ unless text.nil?
1102
+ warning = content_tag('p', :class => 'content_editor_error') do
1103
+ render_icon('warning') + text
1104
+ end
1105
+ return warning
1106
+ end
1107
+ end
1108
+
1109
+ def alchemy_combined_assets
1110
+ alchemy_assets_set
1111
+ end
1112
+
1113
+ # This helper returns a path for use inside a link_to helper.
1114
+ # You may pass a page_layout or an urlname.
1115
+ # Any additional options are passed to the url_helper, so you can add arguments to your url.
1116
+ # Example:
1117
+ # <%= link_to '&raquo order now', page_path_for(:page_layout => 'orderform', :product_id => element.id) %>
1118
+ def page_path_for(options={})
1119
+ return warning("No page_layout, or urlname given. I got #{options.inspect} ") if options[:page_layout].blank? && options[:urlname].blank?
1120
+ if options[:urlname].blank?
1121
+ page = Page.find_by_page_layout(options[:page_layout])
1122
+ return warning("No page found for #{options.inspect} ") if page.blank?
1123
+ urlname = page.urlname
1124
+ else
1125
+ urlname = options[:urlname]
1126
+ end
1127
+ if multi_language?
1128
+ show_page_with_language_path({:urlname => urlname, :lang => @language.code}.merge(options.except(:page_layout, :urlname)))
1129
+ else
1130
+ show_page_path({:urlname => urlname}.merge(options.except(:page_layout, :urlname)))
1131
+ end
1132
+ end
1133
+
1134
+ # Returns the current page.
1135
+ def current_page
1136
+ @page
1137
+ end
1138
+
1139
+ # Renders the partial for the cell with the given name of the current page.
1140
+ # Cell partials are located in +app/views/cells/+ of your project.
1141
+ def render_cell(name)
1142
+ cell = @page.cells.find_by_name(name)
1143
+ return "" if cell.blank?
1144
+ render :partial => "cells/#{name}", :locals => {:cell => cell}
1145
+ end
1146
+
1147
+ # Renders all element partials from given cell.
1148
+ def render_cell_elements(cell)
1149
+ return warning("No cell given.") if cell.blank?
1150
+ ret = ""
1151
+ cell.elements.each do |element|
1152
+ ret << render_element(element)
1153
+ end
1154
+ ret.html_safe
1155
+ end
1156
+
1157
+ # Returns true or false if no elements are in the cell found by name.
1158
+ def cell_empty?(name)
1159
+ cell = @page.cells.find_by_name(name)
1160
+ return true if cell.blank?
1161
+ cell.elements.blank?
1162
+ end
1163
+
1164
+ def necessary_options_for_cropping_provided?(options)
1165
+ options[:crop].to_s == 'true' && !options[:image_size].blank?
1166
+ end
1167
+
1168
+ end