alchemy_cms 2.0.rc3 → 2.0.rc4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (219) hide show
  1. data/.gitignore +3 -1
  2. data/.rspec +1 -2
  3. data/.travis.yml +11 -0
  4. data/.yardopts +0 -1
  5. data/Gemfile +1 -2
  6. data/README.md +14 -0
  7. data/alchemy_cms.gemspec +4 -2
  8. data/app/controllers/admin/clipboard_controller.rb +8 -9
  9. data/app/controllers/admin/contents_controller.rb +4 -2
  10. data/app/controllers/admin/essence_pictures_controller.rb +2 -2
  11. data/app/controllers/admin/layoutpages_controller.rb +2 -0
  12. data/app/controllers/admin/pages_controller.rb +5 -5
  13. data/app/controllers/admin/pictures_controller.rb +2 -1
  14. data/app/controllers/admin/trash_controller.rb +2 -0
  15. data/app/controllers/alchemy_controller.rb +10 -4
  16. data/app/controllers/elements_controller.rb +1 -1
  17. data/app/helpers/admin/elements_helper.rb +32 -1
  18. data/app/helpers/alchemy_helper.rb +15 -818
  19. data/app/helpers/contents_helper.rb +69 -0
  20. data/app/helpers/elements_helper.rb +161 -0
  21. data/app/helpers/essences_helper.rb +167 -0
  22. data/app/helpers/pages_helper.rb +401 -19
  23. data/app/models/attachment.rb +4 -0
  24. data/app/models/element.rb +27 -14
  25. data/app/models/page.rb +75 -38
  26. data/app/views/admin/essence_pictures/destroy.js.erb +1 -1
  27. data/app/views/admin/pages/_create_language_form.html.erb +2 -1
  28. data/app/views/admin/pages/new.html.erb +1 -1
  29. data/app/views/admin/pages/update.js.erb +1 -1
  30. data/app/views/admin/partials/_upload_form.html.erb +2 -2
  31. data/app/views/admin/pictures/index.html.erb +7 -4
  32. data/app/views/essences/_essence_picture_editor.html.erb +1 -3
  33. data/app/views/layouts/alchemy.html.erb +59 -59
  34. data/app/views/layouts/pages.html.erb +2 -4
  35. data/app/views/{partials/_navigation_image_link.html.erb → navigation/_image_link.html.erb} +0 -0
  36. data/app/views/{partials/_navigation_link.html.erb → navigation/_link.html.erb} +1 -1
  37. data/app/views/{partials/_navigation_renderer.html.erb → navigation/_renderer.html.erb} +0 -0
  38. data/app/views/page_layouts/_contact.html.erb +1 -1
  39. data/app/views/page_layouts/_external.html.erb +0 -1
  40. data/app/views/page_layouts/_intro.html.erb +1 -1
  41. data/app/views/page_layouts/_news.html.erb +1 -1
  42. data/app/views/page_layouts/_search.html.erb +1 -1
  43. data/app/views/page_layouts/_standard.html.erb +1 -1
  44. data/assets/images/icons.png +0 -0
  45. data/assets/javascripts/tiny_mce/plugins/inlinepopups/skins/alchemy/window.css +49 -31
  46. data/assets/stylesheets/alchemy.css +111 -91
  47. data/assets/stylesheets/elements.css +12 -16
  48. data/bin/alchemy +1 -1
  49. data/config/alchemy/config.yml +4 -0
  50. data/config/initializers/tinymce_hammer.rb +1 -0
  51. data/config/locales/de.yml +3 -1
  52. data/config/locales/en.yml +2 -0
  53. data/config/routes.rb +6 -4
  54. data/lib/alchemy/capistrano.rb +4 -7
  55. data/lib/alchemy/page_layout.rb +12 -8
  56. data/lib/alchemy/version.rb +1 -1
  57. data/spec/controllers/admin/clipboard_controller_spec.rb +23 -0
  58. data/spec/dummy/db/schema.rb +9 -9
  59. data/spec/factories.rb +24 -6
  60. data/spec/helpers/admin/elements_helper_spec.rb +20 -0
  61. data/spec/helpers/alchemy_helper_spec.rb +41 -0
  62. data/spec/helpers/contents_helper_spec.rb +27 -0
  63. data/spec/helpers/elements_helper_spec.rb +39 -0
  64. data/spec/helpers/essences_helper_spec.rb +49 -0
  65. data/spec/helpers/pages_helper_spec.rb +140 -0
  66. data/spec/integration/security_spec.rb +1 -1
  67. data/spec/integration/standardset_spec.rb +29 -0
  68. data/spec/models/element_spec.rb +49 -0
  69. data/spec/{language_spec.rb → models/language_spec.rb} +0 -0
  70. data/spec/models/page_spec.rb +139 -0
  71. data/spec/{user_spec.rb → models/user_spec.rb} +0 -0
  72. data/spec/page_layout_spec.rb +21 -0
  73. data/spec/routing_spec.rb +53 -0
  74. data/spec/spec_helper.rb +12 -11
  75. metadata +54 -303
  76. data/spec/dummy/config/alchemy/config.yml +0 -199
  77. data/spec/dummy/config/alchemy/elements.yml +0 -91
  78. data/spec/dummy/config/alchemy/page_layouts.yml +0 -29
  79. data/spec/dummy/public/images/alchemy/ajax_loader.gif +0 -0
  80. data/spec/dummy/public/images/alchemy/alchemy-logo.png +0 -0
  81. data/spec/dummy/public/images/alchemy/flags.png +0 -0
  82. data/spec/dummy/public/images/alchemy/gui/navi-tab.png +0 -0
  83. data/spec/dummy/public/images/alchemy/gui/shading.png +0 -0
  84. data/spec/dummy/public/images/alchemy/gui/shading_90.png +0 -0
  85. data/spec/dummy/public/images/alchemy/gui/toggle.png +0 -0
  86. data/spec/dummy/public/images/alchemy/icons.png +0 -0
  87. data/spec/dummy/public/images/alchemy/jquery-sb/select_arrow.gif +0 -0
  88. data/spec/dummy/public/images/alchemy/jquery-sb/select_arrow_bg.gif +0 -0
  89. data/spec/dummy/public/images/alchemy/jquery-sb/select_arrow_bg_hover.gif +0 -0
  90. data/spec/dummy/public/images/alchemy/jquery-ui/ui-icons_666666_256x240.png +0 -0
  91. data/spec/dummy/public/images/alchemy/placeholder.png +0 -0
  92. data/spec/dummy/public/images/alchemy/swfupload/browse_button.png +0 -0
  93. data/spec/dummy/public/javascripts/alchemy/alchemy.element_editor_selector.js +0 -88
  94. data/spec/dummy/public/javascripts/alchemy/alchemy.growler.js +0 -44
  95. data/spec/dummy/public/javascripts/alchemy/alchemy.image_cropper.js +0 -56
  96. data/spec/dummy/public/javascripts/alchemy/alchemy.js +0 -892
  97. data/spec/dummy/public/javascripts/alchemy/alchemy.link_overlay.js +0 -221
  98. data/spec/dummy/public/javascripts/alchemy/alchemy.page_sorter.js +0 -42
  99. data/spec/dummy/public/javascripts/alchemy/alchemy.preview.js +0 -145
  100. data/spec/dummy/public/javascripts/alchemy/jquery-ui.js +0 -428
  101. data/spec/dummy/public/javascripts/alchemy/jquery.Jcrop.min.js +0 -246
  102. data/spec/dummy/public/javascripts/alchemy/jquery.dialogextend.min.js +0 -8
  103. data/spec/dummy/public/javascripts/alchemy/jquery.in-place-edit.js +0 -171
  104. data/spec/dummy/public/javascripts/alchemy/jquery.js +0 -18
  105. data/spec/dummy/public/javascripts/alchemy/jquery.rails.js +0 -315
  106. data/spec/dummy/public/javascripts/alchemy/jquery.sb.min.js +0 -14
  107. data/spec/dummy/public/javascripts/alchemy/jquery.scrollTo-1.4.2-min.js +0 -11
  108. data/spec/dummy/public/javascripts/alchemy/jquery.ui.nestedSortable.js +0 -291
  109. data/spec/dummy/public/javascripts/alchemy/jquery.ui.tabspaging.js +0 -281
  110. data/spec/dummy/public/javascripts/alchemy/swfupload/fileprogress.js +0 -203
  111. data/spec/dummy/public/javascripts/alchemy/swfupload/handlers.js +0 -171
  112. data/spec/dummy/public/javascripts/alchemy/swfupload/queue.js +0 -98
  113. data/spec/dummy/public/javascripts/alchemy/swfupload/swfupload.js +0 -980
  114. data/spec/dummy/public/javascripts/alchemy/swfupload/swfupload.swf +0 -0
  115. data/spec/dummy/public/javascripts/alchemy/tiny_mce/jquery.tinymce.js +0 -1
  116. data/spec/dummy/public/javascripts/alchemy/tiny_mce/langs/de.js +0 -1
  117. data/spec/dummy/public/javascripts/alchemy/tiny_mce/langs/en.js +0 -223
  118. data/spec/dummy/public/javascripts/alchemy/tiny_mce/license.txt +0 -504
  119. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/alchemy_link/editor_plugin.js +0 -43
  120. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/alchemy_link/langs/de.js +0 -4
  121. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/alchemy_link/langs/en.js +0 -4
  122. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/fullscreen/editor_plugin.js +0 -1
  123. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/fullscreen/fullscreen.htm +0 -109
  124. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/inlinepopups/editor_plugin.js +0 -1
  125. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/inlinepopups/skins/alchemy/window.css +0 -402
  126. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/inlinepopups/template.htm +0 -387
  127. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/lists/editor_plugin.js +0 -1
  128. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/paste/editor_plugin.js +0 -1
  129. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/paste/js/pastetext.js +0 -36
  130. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/paste/js/pasteword.js +0 -51
  131. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/paste/langs/de_dlg.js +0 -1
  132. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/paste/langs/en_dlg.js +0 -5
  133. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/paste/pastetext.htm +0 -27
  134. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/paste/pasteword.htm +0 -21
  135. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/table/cell.htm +0 -180
  136. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/table/css/cell.css +0 -17
  137. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/table/css/row.css +0 -25
  138. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/table/css/table.css +0 -13
  139. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/table/editor_plugin.js +0 -1
  140. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/table/js/cell.js +0 -319
  141. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/table/js/merge_cells.js +0 -27
  142. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/table/js/row.js +0 -237
  143. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/table/js/table.js +0 -450
  144. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/table/langs/de_dlg.js +0 -1
  145. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/table/langs/en_dlg.js +0 -75
  146. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/table/merge_cells.htm +0 -32
  147. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/table/row.htm +0 -158
  148. data/spec/dummy/public/javascripts/alchemy/tiny_mce/plugins/table/table.htm +0 -188
  149. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/about.htm +0 -52
  150. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/anchor.htm +0 -26
  151. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/charmap.htm +0 -51
  152. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/color_picker.htm +0 -74
  153. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/editor_template.js +0 -1
  154. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/image.htm +0 -80
  155. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/img/colorpicker.jpg +0 -0
  156. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/img/flash.gif +0 -0
  157. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/img/icons.gif +0 -0
  158. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/img/iframe.gif +0 -0
  159. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/img/pagebreak.gif +0 -0
  160. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/img/quicktime.gif +0 -0
  161. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/img/realmedia.gif +0 -0
  162. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/img/shockwave.gif +0 -0
  163. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/img/trans.gif +0 -0
  164. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/img/video.gif +0 -0
  165. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/img/windowsmedia.gif +0 -0
  166. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/js/about.js +0 -73
  167. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/js/anchor.js +0 -42
  168. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/js/charmap.js +0 -355
  169. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/js/color_picker.js +0 -329
  170. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/js/image.js +0 -247
  171. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/js/link.js +0 -153
  172. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/js/source_editor.js +0 -56
  173. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/langs/de.js +0 -1
  174. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/langs/de_dlg.js +0 -1
  175. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/langs/en.js +0 -68
  176. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/langs/en_dlg.js +0 -54
  177. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/link.htm +0 -57
  178. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/shortcuts.htm +0 -47
  179. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/default/content.css +0 -47
  180. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/default/dialog.css +0 -117
  181. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/default/img/buttons.png +0 -0
  182. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/default/img/items.gif +0 -0
  183. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/default/img/menu_arrow.gif +0 -0
  184. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/default/img/menu_check.gif +0 -0
  185. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/default/img/progress.gif +0 -0
  186. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/default/img/tabs.gif +0 -0
  187. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/default/ui.css +0 -214
  188. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/highcontrast/content.css +0 -23
  189. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/highcontrast/dialog.css +0 -105
  190. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/highcontrast/ui.css +0 -102
  191. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/o2k7/content.css +0 -46
  192. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/o2k7/dialog.css +0 -117
  193. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/o2k7/img/button_bg.png +0 -0
  194. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_black.png +0 -0
  195. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/o2k7/img/button_bg_silver.png +0 -0
  196. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/o2k7/ui.css +0 -217
  197. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/o2k7/ui_black.css +0 -8
  198. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css +0 -5
  199. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/advanced/source_editor.htm +0 -25
  200. data/spec/dummy/public/javascripts/alchemy/tiny_mce/themes/simple/langs/de.js +0 -1
  201. data/spec/dummy/public/javascripts/alchemy/tiny_mce/tiny_mce.js +0 -1
  202. data/spec/dummy/public/javascripts/alchemy/tiny_mce/tiny_mce_popup.js +0 -5
  203. data/spec/dummy/public/javascripts/alchemy/tiny_mce/utils/editable_selects.js +0 -70
  204. data/spec/dummy/public/javascripts/alchemy/tiny_mce/utils/form_utils.js +0 -210
  205. data/spec/dummy/public/javascripts/alchemy/tiny_mce/utils/mctabs.js +0 -162
  206. data/spec/dummy/public/javascripts/alchemy/tiny_mce/utils/validate.js +0 -252
  207. data/spec/dummy/public/stylesheets/alchemy/Jcrop.gif +0 -0
  208. data/spec/dummy/public/stylesheets/alchemy/alchemy.css +0 -3653
  209. data/spec/dummy/public/stylesheets/alchemy/alchemy_tinymce_content.css +0 -94
  210. data/spec/dummy/public/stylesheets/alchemy/alchemy_tinymce_dialog.css +0 -415
  211. data/spec/dummy/public/stylesheets/alchemy/default/img/tabs.gif +0 -0
  212. data/spec/dummy/public/stylesheets/alchemy/elements.css +0 -900
  213. data/spec/dummy/public/stylesheets/alchemy/flags.css +0 -1
  214. data/spec/dummy/public/stylesheets/alchemy/ie6.css +0 -18
  215. data/spec/dummy/public/stylesheets/alchemy/jquery-ui-1.8.7.alchemy.css +0 -2023
  216. data/spec/dummy/public/stylesheets/alchemy/jquery.Jcrop.css +0 -35
  217. data/spec/dummy/public/stylesheets/alchemy/jquery.sb.css +0 -244
  218. data/spec/dummy/public/stylesheets/alchemy/standard_set.css +0 -374
  219. data/spec/page_spec.rb +0 -50
@@ -0,0 +1,69 @@
1
+ module ContentsHelper
2
+
3
+ # Returns a string for the id attribute of a html element for the given content
4
+ def content_dom_id(content)
5
+ return "" if content.nil?
6
+ if content.class == String
7
+ c = Content.find_by_name(content)
8
+ return "" if c.nil?
9
+ else
10
+ c = content
11
+ end
12
+ "#{c.essence_type.underscore}_#{c.id}"
13
+ end
14
+
15
+ # Renders the name of elements content or the default name defined in elements.yml
16
+ def render_content_name(content)
17
+ if content.blank?
18
+ warning('Element is nil')
19
+ return ""
20
+ else
21
+ content_name = content.name_for_label
22
+ end
23
+ if content.description.blank?
24
+ warning("Content #{content.name} is missing its description")
25
+ title = _("Warning: Content '%{contentname}' is missing its description.") % {:contentname => content.name}
26
+ content_name = %(<span class="warning icon" title="#{title}"></span>&nbsp;) + content_name
27
+ end
28
+ content.has_validations? ? "#{content_name}<span class='validation_indicator'>*</span>" : content_name
29
+ end
30
+
31
+ # Renders a link to show the new content overlay
32
+ def render_new_content_link(element)
33
+ link_to_overlay_window(
34
+ _('add new content'),
35
+ new_admin_element_content_path(element),
36
+ {
37
+ :size => '305x40',
38
+ :title => _('Select an content'),
39
+ :overflow => true
40
+ },
41
+ {
42
+ :id => "add_content_for_element_#{element.id}",
43
+ :class => 'button new_content_link'
44
+ }
45
+ )
46
+ end
47
+
48
+ # Renders a link to create a new content in element editor
49
+ def render_create_content_link(element, options = {})
50
+ defaults = {
51
+ :label => _('add new content')
52
+ }
53
+ options = defaults.merge(options)
54
+ link_to(
55
+ options[:label],
56
+ admin_contents_path(
57
+ :content => {
58
+ :name => options[:content_name],
59
+ :element_id => element.id
60
+ }
61
+ ),
62
+ :method => 'post',
63
+ :remote => true,
64
+ :id => "add_content_for_element_#{element.id}",
65
+ :class => 'button new_content_link'
66
+ )
67
+ end
68
+
69
+ end
@@ -1,2 +1,163 @@
1
1
  module ElementsHelper
2
+
3
+ include EssencesHelper
4
+
5
+ # Renders all elements from @page.
6
+ # ---
7
+ # == Options are:
8
+ # :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.
9
+ # :except => [] A list of element names to be rendered. The opposite of the only option.
10
+ # :from_page The Page.page_layout string from which the elements are rendered from, or you even pass a Page object.
11
+ # :count The amount of elements to be rendered (beginns with first element found)
12
+ # :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
13
+ # :sort_by => Content#name A Content name to sort the elements by
14
+ # :reverse => boolean Reverse the rendering order
15
+ #
16
+ # This helper also stores all pages where elements gets rendered on, so we can sweep them later if caching expires!
17
+ #
18
+ def render_elements(options = {})
19
+ default_options = {
20
+ :except => [],
21
+ :only => [],
22
+ :from_page => "",
23
+ :count => nil,
24
+ :offset => nil,
25
+ :locals => {},
26
+ :render_format => "html",
27
+ :fallback => nil
28
+ }
29
+ options = default_options.merge(options)
30
+ if options[:from_page].blank?
31
+ page = @page
32
+ else
33
+ if options[:from_page].class == Page
34
+ page = options[:from_page]
35
+ else
36
+ page = Page.find_all_by_page_layout_and_language_id(options[:from_page], session[:language_id])
37
+ end
38
+ end
39
+ if page.blank?
40
+ warning('Page is nil')
41
+ return ""
42
+ else
43
+ show_non_public = configuration(:cache_pages) ? false : defined?(current_user)
44
+ if page.class == Array
45
+ all_elements = page.collect { |p| p.find_elements(options, show_non_public) }.flatten
46
+ else
47
+ all_elements = page.find_elements(options, show_non_public)
48
+ end
49
+ unless options[:sort_by].blank?
50
+ all_elements = all_elements.sort_by { |e| e.contents.detect { |c| c.name == options[:sort_by] }.ingredient }
51
+ end
52
+ all_elements.reverse! if options[:reverse_sort] || options[:reverse]
53
+ element_string = ""
54
+ if options[:fallback]
55
+ unless all_elements.detect { |e| e.name == options[:fallback][:for] }
56
+ if from = Page.find_by_page_layout(options[:fallback][:from])
57
+ all_elements += from.elements.find_all_by_name(options[:fallback][:with].blank? ? options[:fallback][:for] : options[:fallback][:with])
58
+ end
59
+ end
60
+ end
61
+ all_elements.each_with_index do |element, i|
62
+ element_string += render_element(element, :view, options, i+1)
63
+ end
64
+ element_string.html_safe
65
+ end
66
+ end
67
+
68
+ # This helper renders the Element partial for either the view or the editor part.
69
+ # Generate element partials with ./script/generate elements
70
+ def render_element(element, part = :view, options = {}, i = 1)
71
+ begin
72
+ if element.blank?
73
+ warning('Element is nil')
74
+ render :partial => "elements/#{part}_not_found", :locals => {:name => 'nil'}
75
+ else
76
+ default_options = {
77
+ :shorten_to => nil,
78
+ :render_format => "html"
79
+ }
80
+ options = default_options.merge(options)
81
+ element.store_page(@page) if part == :view
82
+ path1 = "#{Rails.root}/app/views/elements/"
83
+ path2 = "#{Rails.root}/vendor/plugins/alchemy/app/views/elements/"
84
+ partial_name = "_#{element.name.underscore}_#{part}.html.erb"
85
+ locals = options.delete(:locals)
86
+ render(
87
+ :partial => "elements/#{element.name.underscore}_#{part}.#{options[:render_format]}.erb",
88
+ :locals => {
89
+ :element => element,
90
+ :options => options,
91
+ :counter => i
92
+ }.merge(locals || {})
93
+ )
94
+ end
95
+ rescue ActionView::MissingTemplate
96
+ warning(%(
97
+ Element #{part} partial not found for #{element.name}.\n
98
+ Looking for #{partial_name}, but not found
99
+ neither in #{path1}
100
+ nor in #{path2}
101
+ Use rails generate alchemy:elements to generate them.
102
+ Maybe you still have old style partial names? (like .rhtml). Then please rename them in .html.erb'
103
+ ))
104
+ render :partial => "elements/#{part}_not_found", :locals => {:name => element.name, :error => "Element #{part} partial not found. Use rails generate alchemy:elements to generate them."}
105
+ end
106
+ end
107
+
108
+ # Returns all public elements found by Element.name.
109
+ # Pass a count to return only an limited amount of elements.
110
+ def all_elements_by_name(name, options = {})
111
+ warning('options[:language] option not allowed any more in all_elements_by_name helper') unless options[:language].blank?
112
+ default_options = {
113
+ :count => :all,
114
+ :from_page => :all
115
+ }
116
+ options = default_options.merge(options)
117
+ if options[:from_page] == :all
118
+ elements = Element.find_all_by_name_and_public(name, true, :limit => options[:count] == :all ? nil : options[:count])
119
+ elsif options[:from_page].class == String
120
+ page = Page.find_by_page_layout_and_language_id(options[:from_page], session[:language_id])
121
+ return [] if page.blank?
122
+ elements = page.elements.find_all_by_name_and_public(name, true, :limit => options[:count] == :all ? nil : options[:count])
123
+ else
124
+ elements = options[:from_page].elements.find_all_by_name_and_public(name, true, :limit => options[:count] == :all ? nil : options[:count])
125
+ end
126
+ end
127
+
128
+ # Returns the public element found by Element.name from the given public Page, either by Page.id or by Page.urlname
129
+ def element_from_page(options = {})
130
+ default_options = {
131
+ :page_urlname => "",
132
+ :page_id => nil,
133
+ :element_name => ""
134
+ }
135
+ options = default_options.merge(options)
136
+ if options[:page_id].blank?
137
+ page = Page.find_by_urlname_and_public(options[:page_urlname], true)
138
+ else
139
+ page = Page.find_by_id_and_public(options[:page_id], true)
140
+ end
141
+ return "" if page.blank?
142
+ element = page.elements.find_by_name_and_public(options[:element_name], true)
143
+ return element
144
+ end
145
+
146
+ # Returns a string for the id attribute of a html element for the given element
147
+ def element_dom_id(element)
148
+ return "" if element.nil?
149
+ "#{element.name}_#{element.id}"
150
+ end
151
+
152
+ # Renders the data-alchemy-element HTML attribut used for the preview window hover effect.
153
+ def element_preview_code(element)
154
+ return "" if element.nil?
155
+ " data-alchemy-element='#{element.id}'" if @preview_mode && element.page == @page
156
+ end
157
+
158
+ # Returns the full url containing host, page and anchor for the given element
159
+ def full_url_for_element(element)
160
+ "http://" + request.env["HTTP_HOST"] + "/" + element.page.urlname + "##{element.name}_#{element.id}"
161
+ end
162
+
2
163
  end
@@ -0,0 +1,167 @@
1
+ module EssencesHelper
2
+
3
+ include ContentsHelper
4
+
5
+ # Renders the Content view partial from the passed Element for passed content name.
6
+ # For options see -> render_essence
7
+ def render_essence_view_by_name(element, name, options = {}, html_options = {})
8
+ if element.blank?
9
+ warning('Element is nil')
10
+ return ""
11
+ end
12
+ content = element.content_by_name(name)
13
+ render_essence(content, :view, {:for_view => options}, html_options)
14
+ end
15
+
16
+ # Renders the Content partial that is given (:editor, or :view).
17
+ # You can pass several options that are used by the different contents.
18
+ #
19
+ # For the view partial:
20
+ # :image_size => "111x93" Used by EssencePicture to render the image via RMagick to that size.
21
+ # :css_class => "" This css class gets attached to the content view.
22
+ # :date_format => "Am %d. %m. %Y, um %H:%Mh" Espacially fot the EssenceDate. See Date.strftime for date formatting.
23
+ # :caption => true Pass true to enable that the EssencePicture.caption value gets rendered.
24
+ # :blank_value => "" Pass a String that gets rendered if the content.essence is blank.
25
+ #
26
+ # For the editor partial:
27
+ # :css_class => "" This css class gets attached to the content editor.
28
+ # :last_image_deletable => false Pass true to enable that the last image of an imagecollection (e.g. image gallery) is deletable.
29
+ def render_essence(content, part = :view, options = {}, html_options = {})
30
+ if content.nil?
31
+ return part == :view ? "" : warning('Content is nil', _("content_not_found"))
32
+ elsif content.essence.nil?
33
+ return part == :view ? "" : warning('Essence is nil', _("content_essence_not_found"))
34
+ end
35
+ defaults = {
36
+ :for_editor => {
37
+ :as => 'text_field',
38
+ :css_class => 'long',
39
+ :render_format => "html"
40
+ },
41
+ :for_view => {
42
+ :image_size => "120x90",
43
+ :css_class => "",
44
+ :date_format => "%d. %m. %Y, %H:%Mh",
45
+ :caption => true,
46
+ :blank_value => "",
47
+ :render_format => "html"
48
+ }
49
+ }
50
+ if options["for_#{part}".to_sym].nil?
51
+ options_for_partial = defaults["for_#{part}".to_sym]
52
+ else
53
+ options_for_partial = defaults.fetch("for_#{part}".to_sym).merge(options["for_#{part}".to_sym])
54
+ end
55
+ options = options.merge(defaults)
56
+ render(
57
+ :partial => "essences/#{content.essence.class.name.underscore}_#{part.to_s}.#{options_for_partial[:render_format]}.erb",
58
+ :locals => {
59
+ :content => content,
60
+ :options => options_for_partial,
61
+ :html_options => html_options
62
+ }
63
+ )
64
+ end
65
+
66
+ # Renders the Content view partial from the given Content.
67
+ # For options see -> render_essence
68
+ def render_essence_view(content, options = {}, html_options = {})
69
+ render_essence(content, :view, {:for_view => options}, html_options)
70
+ end
71
+
72
+ # Renders the Content view partial from the given Element for the essence_type (e.g. EssenceRichtext).
73
+ # For multiple contents of same kind inside one element just pass a position so that will be rendered.
74
+ # Otherwise the first content found for this type will be rendered.
75
+ # For options see -> render_essence
76
+ def render_essence_view_by_type(element, type, position = 1, options = {}, html_options = {})
77
+ if element.blank?
78
+ warning('Element is nil')
79
+ return ""
80
+ end
81
+ if position == 1
82
+ content = element.content_by_type(type)
83
+ else
84
+ content = element.contents.find_by_essence_type_and_position(type, position)
85
+ end
86
+ render_essence(content, :view, :for_view => options)
87
+ end
88
+
89
+ # Renders the Content view partial from the given Element by position (e.g. 1).
90
+ # For options see -> render_essence
91
+ def render_essence_view_by_position(element, position, options = {}, html_options = {})
92
+ if element.blank?
93
+ warning('Element is nil')
94
+ return ""
95
+ end
96
+ content = element.contents.find_by_position(position)
97
+ render_essence(content, :view, {:for_view => options}, html_options)
98
+ end
99
+
100
+ # Renders the Content editor partial from the given Content.
101
+ # For options see -> render_essence
102
+ def render_essence_editor(content, options = {})
103
+ render_essence(content, :editor, :for_editor => options)
104
+ end
105
+
106
+ # Renders the Content editor partial from essence_type.
107
+ #
108
+ # Options are:
109
+ # * element (Element) - the Element the contents are in (obligatory)
110
+ # * type (String) - the type of Essence (obligatory)
111
+ # * options (Hash):
112
+ # ** :position (Integer) - The position of the Content inside the Element. I.E. for getting the n-th EssencePicture. Default is 1 (the first)
113
+ # ** :all (String) - Pass :all to get all Contents of that name. Default false
114
+ # * editor_options (Hash) - Will be passed to the render_essence_editor partial renderer
115
+ #
116
+ def render_essence_editor_by_type(element, essence_type, options = {}, editor_options = {})
117
+ return warning('Element is nil', _("no_element_given")) if element.blank?
118
+ return warning('EssenceType is blank', _("No EssenceType given")) if essence_type.blank?
119
+ defaults = {
120
+ :position => 1,
121
+ :all => false
122
+ }
123
+ options = defaults.merge(options)
124
+ return_string = ""
125
+ if options[:all]
126
+ contents = element.contents.find_all_by_essence_type_and_name(essence_type, options[:all])
127
+ contents.each do |content|
128
+ return_string << render_essence(content, :editor, :for_editor => editor_options)
129
+ end
130
+ else
131
+ content = element.contents.find_by_essence_type_and_position(essence_type, options[:position])
132
+ return_string = render_essence(content, :editor, :for_editor => editor_options)
133
+ end
134
+ return_string
135
+ end
136
+
137
+ # Renders the Content editor partial from the given Element by position (e.g. 1).
138
+ # For options see -> render_essence
139
+ def render_essence_editor_by_position(element, position, options = {})
140
+ if element.blank?
141
+ warning('Element is nil')
142
+ return ""
143
+ end
144
+ content = element.contents.find_by_position(position)
145
+ render_essence(content, :editor, :for_editor => options)
146
+ end
147
+
148
+ # Renders the Content editor partial found in views/contents/ for the content with name inside the passed Element.
149
+ # For options see -> render_essence
150
+ #
151
+ # Content creation on the fly:
152
+ #
153
+ # If you update the elements.yml file after creating an element this helper displays a error message with an option to create the content.
154
+ #
155
+ def render_essence_editor_by_name(element, name, options = {})
156
+ if element.blank?
157
+ return warning('Element is nil', _("no_element_given"))
158
+ end
159
+ content = element.content_by_name(name)
160
+ if content.blank?
161
+ render :partial => 'admin/contents/missing', :locals => {:element => element, :name => name}
162
+ else
163
+ render_essence(content, :editor, :for_editor => options)
164
+ end
165
+ end
166
+
167
+ end
@@ -1,12 +1,9 @@
1
1
  module PagesHelper
2
2
 
3
- # DEPRICATED! Use Element.preview_text instead.
4
- def get_preview_text element
5
- element.preview_text
6
- end
3
+ include ElementsHelper
7
4
 
8
- def render_classes classes=[]
9
- s = classes.uniq.delete_if{|x| x == nil || x.blank?}.join(" ")
5
+ def render_classes(classes=[])
6
+ s = classes.uniq.delete_if { |x| x.blank? }.join(" ")
10
7
  s.blank? ? "" : "class='#{s}'"
11
8
  end
12
9
 
@@ -72,6 +69,7 @@ module PagesHelper
72
69
  end
73
70
 
74
71
  # helper for language switching
72
+ # returns a string with links or nil
75
73
  def language_switches(options={})
76
74
  default_options = {
77
75
  :linkname => :name,
@@ -84,48 +82,432 @@ module PagesHelper
84
82
  }
85
83
  options = default_options.merge(options)
86
84
  if multi_language?
87
- languages = []
85
+ language_links = []
88
86
  pages = (options[:link_to_public_child] == true) ? Page.language_roots : Page.public_language_roots
87
+ return nil if (pages.blank? || pages.length == 1)
89
88
  pages.each_with_index do |page, i|
90
89
  if(options[:link_to_page_with_layout] != nil)
91
- page_found_by_layout = Page.find_by_page_layout_and_language_id(options[:link_to_page_with_layout].to_s, page.language)
90
+ page_found_by_layout = Page.where(:page_layout => options[:link_to_page_with_layout].to_s, :language_id => page.language_id)
92
91
  end
93
92
  page = page_found_by_layout || page
94
93
  page = (options[:link_to_public_child] ? (page.first_public_child.blank? ? nil : page.first_public_child) : nil) if !page.public?
95
-
96
94
  if !page.blank?
97
95
  active = session[:language_id] == page.language.id
98
96
  linkname = page.language.label(options[:linkname])
99
97
  if options[:as_select_box]
100
- languages << [linkname, show_page_url(:urlname => page.urlname, :lang => page.language.code)]
98
+ language_links << [linkname, show_page_url(:urlname => page.urlname, :lang => page.language.code)]
101
99
  else
102
- languages << link_to(
100
+ language_links << link_to(
103
101
  "#{content_tag(:span, '', :class => "flag")}#{ content_tag(:span, linkname)}".html_safe,
104
102
  show_page_path(:urlname => page.urlname, :lang => page.language.code),
105
103
  :class => "#{(active ? 'active ' : nil)}#{page.language.code} #{(i == 0) ? 'first' : (i==pages.length-1) ? 'last' : nil}",
106
- :title => options[:show_title] ? I18n.t("alchemy.languages.#{page.language.code}.title", :default => page.language.name) : nil
104
+ :title => options[:show_title] ? I18n.t("alchemy.language_links.#{page.language.code}.title", :default => page.language.name) : nil
107
105
  )
108
106
  end
109
107
  end
108
+ # when last iteration and we have just one language_link,
109
+ # we dont need to render it.
110
+ if (i==pages.length-1) && language_links.length == 1
111
+ return nil
112
+ end
110
113
  end
111
- languages.reverse! if options[:reverse]
114
+ return nil if language_links.empty? || language_links.length == 1
115
+ language_links.reverse! if options[:reverse]
112
116
  if options[:as_select_box]
113
117
  return select_tag(
114
118
  'language',
115
119
  options_for_select(
116
- languages,
120
+ language_links,
117
121
  show_page_url(:urlname => @page.urlname, :lang => @page.language.code)
118
122
  ),
119
123
  :onchange => "window.location=this.value"
120
124
  )
121
125
  else
122
- if options[:spacer].blank?
123
- return languages.html_safe
124
- else
125
- return languages.join(options[:spacer]).html_safe
126
- end
126
+ raw(language_links.join(options[:spacer]))
127
127
  end
128
+ else
129
+ nil
130
+ end
131
+ end
132
+
133
+ # Renders the layout from @page.page_layout. File resists in /app/views/page_layouts/_LAYOUT-NAME.html.erb
134
+ def render_page_layout(options={})
135
+ default_options = {
136
+ :render_format => "html"
137
+ }
138
+ options = default_options.merge(options)
139
+ render :partial => "page_layouts/#{@page.page_layout.downcase}.#{options[:render_format]}.erb"
140
+ rescue ActionView::MissingTemplate
141
+ warning("PageLayout: '#{@page.page_layout}' not found. Rendering standard page_layout.")
142
+ render :partial => "page_layouts/standard"
143
+ end
144
+
145
+ def sitename_from_header_page
146
+ header_page = Page.find_by_page_layout_and_layoutpage('layout_header', true)
147
+ return "" if header_page.nil?
148
+ page_title = header_page.elements.find_by_name('sitename')
149
+ return "" if page_title.nil?
150
+ page_title.ingredient('name')
151
+ end
152
+
153
+ # == This helper renders the navigation.
154
+ #
155
+ # It produces a html <ul><li></li></ul> structure with all necessary classes and ids so you can produce every navigation the web uses today.
156
+ # I.E. dropdown-navigations, simple mainnavigations or even complex nested ones.
157
+ #
158
+ # === En detail:
159
+ #
160
+ # <ul class="navigation_level_1">
161
+ # <li class="first home"><a href="/home" class="active" title="Homepage" lang="en" data-page-id="1">Homepage</a></li>
162
+ # <li class="contact"><a href="/contact" title="Contact" lang="en" data-page-id="2">Contact</a></li>
163
+ # <li class="last imprint"><a href="/imprint" title="Imprint" lang="en" data-page-id="3">Imprint</a></li>
164
+ # </ul>
165
+ #
166
+ # As you can see: Everything you need.
167
+ #
168
+ # Not pleased with the way Alchemy produces the navigation structure?
169
+ # Then feel free to overwrite the partials (_renderer.html.erb and _link.html.erb) found in +views/navigation/+ or pass different partials via the options +:navigation_partial+ and +:navigation_link_partial+.
170
+ #
171
+ # === The options are:
172
+ #
173
+ # :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.
174
+ # :all_sub_menues => false
175
+ # :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.
176
+ # :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 :)
177
+ # :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 ^_^
178
+ # :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.
179
+ # :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.
180
+ # :show_title => true For our beloved SEOs :). Appends a title attribute to all links and places the page.title content into it.
181
+ # :restricted_only => nil Render only restricted pages.
182
+ # :show_title => true Show a title on navigation links. Title attribute from page.
183
+ # :reverse => false Reverse the navigation
184
+ # :reverse_children => false Reverse the nested children
185
+ #
186
+ def render_navigation(options = {})
187
+ default_options = {
188
+ :submenu => false,
189
+ :all_sub_menues => false,
190
+ :from_page => @root_page || Page.language_root_for(session[:language_id]),
191
+ :spacer => "",
192
+ :navigation_partial => "navigation/renderer",
193
+ :navigation_link_partial => "navigation/link",
194
+ :show_nonactive => false,
195
+ :restricted_only => nil,
196
+ :show_title => true,
197
+ :reverse => false,
198
+ :reverse_children => false
199
+ }
200
+ options = default_options.merge(options)
201
+ if options[:from_page].is_a?(String)
202
+ page = Page.find_by_page_layout_and_language_id(options[:from_page], session[:language_id])
203
+ else
204
+ page = options[:from_page]
205
+ end
206
+ if page.blank?
207
+ warning("No Page found for #{options[:from_page]}")
208
+ return ""
209
+ end
210
+ conditions = {
211
+ :parent_id => page.id,
212
+ :restricted => options[:restricted_only] || false,
213
+ :visible => true
214
+ }
215
+ if options[:restricted_only].nil?
216
+ conditions.delete(:restricted)
217
+ end
218
+ pages = Page.where(conditions).order("lft ASC")
219
+ if options[:reverse]
220
+ pages.reverse!
221
+ end
222
+ render :partial => options[:navigation_partial], :locals => {:options => options, :pages => pages}
223
+ end
224
+
225
+ # 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.
226
+ # 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.
227
+ # 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
228
+ # 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.
229
+ # Normally there is no need to change the level parameter, just in a few special cases.
230
+ def render_subnavigation(options = {})
231
+ default_options = {
232
+ :from_page => @page,
233
+ :level => 2
234
+ }
235
+ options = default_options.merge(options)
236
+ if !options[:from_page].nil?
237
+ if (options[:from_page].children.blank? && options[:from_page].level > options[:level])
238
+ options = options.merge(:from_page => Page.find(options[:from_page].parent_id))
239
+ end
240
+ render_navigation(options)
241
+ else
242
+ return nil
243
+ end
244
+ end
245
+
246
+ # returns true if page is in the active branch
247
+ def page_active?(page)
248
+ @breadcrumb ||= breadcrumb(@page)
249
+ @breadcrumb.include?(page)
250
+ end
251
+
252
+ # Returns a HTML string for a linked breadcrumb from root to current page.
253
+ #
254
+ # == Options:
255
+ #
256
+ # :seperator => %(<span class="seperator">></span>) Maybe you don't want this seperator. Pass another one.
257
+ # :page => @page Pass a different Page instead of the default (@page).
258
+ # :without => nil Pass Pageobject or array of Pages that must not be displayed.
259
+ # :public_only => false Pass boolean for displaying hidden pages only.
260
+ # :visible_only => true Pass boolean for displaying (in navigation) visible pages only.
261
+ # :restricted_only => false Pass boolean for displaying restricted pages only.
262
+ # :reverse => false Pass boolean for displaying reversed breadcrumb.
263
+ #
264
+ def render_breadcrumb(options={})
265
+ default_options = {
266
+ :seperator => %(<span class="seperator">&gt;</span>),
267
+ :page => @page,
268
+ :without => nil,
269
+ :public_only => false,
270
+ :visible_only => true,
271
+ :restricted_only => false,
272
+ :reverse => false
273
+ }
274
+ options = default_options.merge(options)
275
+ pages = breadcrumb(options[:page])
276
+ pages.delete(Page.root)
277
+ unless options[:without].nil?
278
+ unless options[:without].class == Array
279
+ pages.delete(options[:without])
280
+ else
281
+ pages = pages - options[:without]
282
+ end
283
+ end
284
+ if options[:visible_only]
285
+ pages.reject! { |p| !p.visible? }
286
+ end
287
+ if options[:public_only]
288
+ pages.reject! { |p| !p.public? }
289
+ end
290
+ if options[:restricted_only]
291
+ pages.reject! { |p| !p.restricted? }
292
+ end
293
+ if options[:reverse]
294
+ pages.reverse!
295
+ end
296
+ bc = []
297
+ pages.each do |page|
298
+ urlname = page.urlname
299
+ css_class = page.name == @page.name ? "active" : nil
300
+ if page == pages.last
301
+ css_class = css_class.blank? ? "last" : [css_class, "last"].join(" ")
302
+ elsif page == pages.first
303
+ css_class = css_class.blank? ? "first" : [css_class, "first"].join(" ")
304
+ end
305
+ url = show_page_path(:urlname => urlname, :lang => multi_language? ? page.language_code : nil)
306
+ bc << link_to(h(page.name), url, :class => css_class, :title => page.title)
307
+ end
308
+ bc.join(options[:seperator]).html_safe
309
+ end
310
+
311
+ # Returns an array of all pages in the same branch from current.
312
+ # I.e. used to find the active page in navigation.
313
+ def breadcrumb(current)
314
+ return [] if current.nil?
315
+ result = Array.new
316
+ result << current
317
+ while current = current.parent
318
+ result << current
128
319
  end
320
+ return result.reverse
321
+ end
322
+
323
+ # Returns @page.title
324
+ #
325
+ # The options are:
326
+ #
327
+ # :prefix => ""
328
+ # :seperator => "|"
329
+ #
330
+ # == Webdevelopers:
331
+ #
332
+ # Please use the render_meta_data() helper. There all important meta information gets rendered in one helper.
333
+ # So you dont have to worry about anything.
334
+ #
335
+ def render_page_title(options={})
336
+ default_options = {
337
+ :prefix => "",
338
+ :seperator => "|"
339
+ }
340
+ default_options.update(options)
341
+ unless @page.title.blank?
342
+ h("#{default_options[:prefix]} #{default_options[:seperator]} #{@page.title}")
343
+ else
344
+ h("")
345
+ end
346
+ end
347
+
348
+ # Returns a complete html <title> tag for the <head> part of the html document.
349
+ #
350
+ # == Webdevelopers:
351
+ #
352
+ # Please use the render_meta_data() helper. There all important meta information gets rendered in one helper.
353
+ # So you dont have to worry about anything.
354
+ #
355
+ def render_title_tag(options={})
356
+ default_options = {
357
+ :prefix => "",
358
+ :seperator => "|"
359
+ }
360
+ options = default_options.merge(options)
361
+ title = render_page_title(options)
362
+ %(<title>#{title}</title>).html_safe
363
+ end
364
+
365
+ # Renders a html <meta> tag for :name => "" and :content => ""
366
+ #
367
+ # == Webdevelopers:
368
+ #
369
+ # Please use the render_meta_data() helper. There all important meta information gets rendered in one helper.
370
+ # So you dont have to worry about anything.
371
+ #
372
+ def render_meta_tag(options={})
373
+ default_options = {
374
+ :name => "",
375
+ :default_language => "de",
376
+ :content => ""
377
+ }
378
+ options = default_options.merge(options)
379
+ lang = (@page.language.blank? ? options[:default_language] : @page.language.code)
380
+ %(<meta name="#{options[:name]}" content="#{options[:content]}" lang="#{lang}" />).html_safe
381
+ end
382
+
383
+ # Renders a html <meta http-equiv="Content-Language" content="#{lang}" /> for @page.language.
384
+ #
385
+ # == Webdevelopers:
386
+ #
387
+ # Please use the render_meta_data() helper. There all important meta information gets rendered in one helper.
388
+ # So you dont have to worry about anything.
389
+ #
390
+ def render_meta_content_language_tag(options={})
391
+ default_options = {
392
+ :default_language => "de"
393
+ }
394
+ options = default_options.merge(options)
395
+ lang = (@page.language_code.blank? ? options[:default_language] : @page.language_code)
396
+ %(<meta http-equiv="Content-Language" content="#{lang}" />).html_safe
397
+ end
398
+
399
+ # = This helper takes care of all important meta tags for your @page.
400
+ #
401
+ # 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.
402
+ #
403
+ # 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:
404
+ #
405
+ # Title = Homepage
406
+ # Description = Your page description
407
+ # Keywords: cms, ruby, rubyonrails, rails, software, development, html, javascript, ajax
408
+ #
409
+ # Then placing +render_meta_data(:title_prefix => "company", :title_seperator => "-")+ into the <head> part of the +pages.html.erb+ layout produces:
410
+ #
411
+ # <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
412
+ # <meta http-equiv="Content-Language" content="de" />
413
+ # <title>Company - #{@page.title}</title>
414
+ # <meta name="description" content="Your page description" />
415
+ # <meta name="keywords" content="cms, ruby, rubyonrails, rails, software, development, html, javascript, ajax" />
416
+ # <meta name="generator" content="Alchemy VERSION" />
417
+ # <meta name="date" content="Tue Dec 16 10:21:26 +0100 2008" />
418
+ # <meta name="robots" content="index, follow" />
419
+ #
420
+ def render_meta_data options={}
421
+ if @page.blank?
422
+ warning("No Page found!")
423
+ return nil
424
+ end
425
+ default_options = {
426
+ :title_prefix => "",
427
+ :title_seperator => "|",
428
+ :default_lang => "de"
429
+ }
430
+ options = default_options.merge(options)
431
+ #render meta description of the root page from language if the current meta description is empty
432
+ if @page.meta_description.blank?
433
+ description = Page.find_by_language_root_and_language_id(true, session[:language_id]).meta_description rescue ""
434
+ else
435
+ description = @page.meta_description
436
+ end
437
+ #render meta keywords of the root page from language if the current meta keywords is empty
438
+ if @page.meta_keywords.blank?
439
+ keywords = Page.find_by_language_root_and_language_id(true, session[:language_id]).meta_keywords rescue ""
440
+ else
441
+ keywords = @page.meta_keywords
442
+ end
443
+ robot = "#{@page.robot_index? ? "" : "no"}index, #{@page.robot_follow? ? "" : "no"}follow"
444
+ meta_string = %(
445
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
446
+ #{render_meta_content_language_tag}
447
+ #{render_title_tag( :prefix => options[:title_prefix], :seperator => options[:title_seperator])}
448
+ #{render_meta_tag( :name => "description", :content => description)}
449
+ #{render_meta_tag( :name => "keywords", :content => keywords)}
450
+ <meta name="generator" content="Alchemy #{Alchemy::VERSION}" />
451
+ <meta name="date" content="#{@page.updated_at}" />
452
+ <meta name="robots" content="#{robot}" />
453
+ )
454
+ if @page.contains_feed?
455
+ meta_string += %(
456
+ <link rel="alternate" type="application/rss+xml" title="RSS" href="#{multi_language? ? show_page_url(:protocol => 'feed', :urlname => @page.urlname, :lang => @page.language_code, :format => :rss) : show_page_url(:protocol => 'feed', :urlname => @page.urlname, :format => :rss)}" />
457
+ )
458
+ end
459
+ return meta_string.html_safe
460
+ end
461
+
462
+ # This helper returns a path for use inside a link_to helper.
463
+ #
464
+ # You may pass a page_layout or an urlname.
465
+ # Any additional options are passed to the url_helper, so you can add arguments to your url.
466
+ #
467
+ # Example:
468
+ #
469
+ # <%= link_to '&raquo order now', page_path_for(:page_layout => 'orderform', :product_id => element.id) %>
470
+ #
471
+ def page_path_for(options={})
472
+ return warning("No page_layout, or urlname given. I got #{options.inspect} ") if options[:page_layout].blank? && options[:urlname].blank?
473
+ if options[:urlname].blank?
474
+ page = Page.find_by_page_layout(options[:page_layout])
475
+ return warning("No page found for #{options.inspect} ") if page.blank?
476
+ urlname = page.urlname
477
+ else
478
+ urlname = options[:urlname]
479
+ end
480
+ show_page_path({:urlname => urlname, :lang => multi_language? ? session[:language_code] : nil}.merge(options.except(:page_layout, :urlname, :lang)))
481
+ end
482
+
483
+ # Renders the partial for the cell with the given name of the current page.
484
+ # Cell partials are located in +app/views/cells/+ of your project.
485
+ def render_cell(name)
486
+ cell = @page.cells.find_by_name(name)
487
+ return "" if cell.blank?
488
+ render :partial => "cells/#{name}", :locals => {:cell => cell}
489
+ end
490
+
491
+ # Renders all element partials from given cell.
492
+ def render_cell_elements(cell)
493
+ return warning("No cell given.") if cell.blank?
494
+ ret = ""
495
+ cell.elements.each do |element|
496
+ ret << render_element(element)
497
+ end
498
+ ret.html_safe
499
+ end
500
+
501
+ # Returns true or false if no elements are in the cell found by name.
502
+ def cell_empty?(name)
503
+ cell = @page.cells.find_by_name(name)
504
+ return true if cell.blank?
505
+ cell.elements.blank?
506
+ end
507
+
508
+ # Include this in your layout file to have element selection magic in the page edit preview window.
509
+ def alchemy_preview_mode_code
510
+ javascript_include_tag("alchemy/alchemy.preview") if @preview_mode
129
511
  end
130
512
 
131
513
  end