Module: Alchemy::ElementsHelper

Includes:
ElementsBlockHelper, EssencesHelper, UrlHelper
Included in:
Admin::ElementsHelper, PagesHelper
Defined in:
app/helpers/alchemy/elements_helper.rb

Overview

This helpers are useful to render elements from pages.

The most important helper for frontend developers is the #render_elements helper.

Instance Method Summary (collapse)

Methods included from ElementsBlockHelper

#element_editor_for, #element_view_for

Methods included from UrlHelper

#download_alchemy_attachment_path, #download_alchemy_attachment_url, #page_path_for, #show_alchemy_page_path, #show_alchemy_page_url, #show_alchemy_picture_path, #show_alchemy_picture_url, #show_page_path_params, #show_picture_path_params

Methods included from EssencesHelper

#render_essence, #render_essence_picture_view, #render_essence_view, #render_essence_view_by_name, #render_essence_view_by_type

Instance Method Details

- (Object) all_elements_by_name(name, options = {})

Note:

When passing a String for options :from_page, it must be a page_layout name.

This helper returns all published elements with the given name.

Parameters:

  • options (Hash) (defaults to: {})

    Additional options.

Options Hash (options):

  • :count (Number)

    The amount of elements to be returned.

  • :from_page (Alchemy::Page/String)

    Only elements associated with this page are returned.



212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'app/helpers/alchemy/elements_helper.rb', line 212

def all_elements_by_name(name, options = {})
  warning('options[:language] option not allowed any more in all_elements_by_name helper') unless options[:language].blank?
  options = {
    count: :all,
    from_page: :all
  }.merge(options)

  case options[:from_page]
  when :all
    return Element.published.where(name: name).limit(options[:count] == :all ? nil : options[:count])
  when String
    page = Page.with_language(session[:language_id]).find_by_page_layout(options[:from_page])
  else
    page = options[:from_page]
  end

  return [] if page.blank?
  page.elements.published.where(name: name).limit(options[:count] == :all ? nil : options[:count])
end

- (Object) element_dom_id(element)

Returns a string for the id attribute of a html element for the given element



268
269
270
271
# File 'app/helpers/alchemy/elements_helper.rb', line 268

def element_dom_id(element)
  return "" if element.nil?
  "#{element.name}_#{element.id}".html_safe
end

- (Object) element_from_page(options = {})

This helper returns a published element found by the given name and the given published Page, either by Page.id or by Page.urlname

Parameters:

  • options (Hash) (defaults to: {})

    Additional options.

Options Hash (options):

  • :page_urlname (String)

    The urlname of the Page the element is associated with

  • :page_id (Integer)

    The id of the Page the element is associated with



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'app/helpers/alchemy/elements_helper.rb', line 243

def element_from_page(options = {})
  default_options = {
    page_urlname: "",
    page_id: nil,
    element_name: ""
  }.merge(options)

  page = case options[:page_id]
  when nil
    Page.published.find_by_urlname(options[:page_urlname])
  else
    Page.published.find_by_id(options[:page_id])
  end

  return "" if page.blank?
  page.elements.published.find_by_name(options[:element_name])
end

- (Object) element_preview_code(element)

Renders the HTML tag attributes required for preview mode.



274
275
276
# File 'app/helpers/alchemy/elements_helper.rb', line 274

def element_preview_code(element)
  tag_options(element_preview_code_attributes(element))
end

- (Object) element_preview_code_attributes(element)

Returns a hash containing the HTML tag attributes required for preview mode.



279
280
281
282
# File 'app/helpers/alchemy/elements_helper.rb', line 279

def element_preview_code_attributes(element)
  return {} unless element.present? && @preview_mode && element.page == @page
  { :data-alchemy-element' => element.id }
end

- (String) element_tags(element, options = {})

Returns the element's tags information as a string. Parameters and options are equivalent to #element_tags_attributes.

Returns:

  • (String)

    HTML tag attributes containing the element's tag information.

See Also:



297
298
299
# File 'app/helpers/alchemy/elements_helper.rb', line 297

def element_tags(element, options = {})
  tag_options(element_tags_attributes(element, options))
end

- (Hash) element_tags_attributes(element, options = {})

Returns the element's tags information as an attribute hash.

Parameters:

Options Hash (options):

  • :formatter (Proc) — default: 'lambda { |tags| tags.join(' ') }'

    Lambda converting array of tags to a string.

Returns:

  • (Hash)

    HTML tag attributes containing the element's tag information.



313
314
315
316
317
318
319
320
# File 'app/helpers/alchemy/elements_helper.rb', line 313

def element_tags_attributes(element, options = {})
  options = {
    formatter: lambda { |tags| tags.join(' ') }
  }.merge(options)

  return {} if !element.taggable? || element.tag_list.blank?
  { :data-element-tags' => options[:formatter].call(element.tag_list) }
end

- (Object) full_url_for_element(element)

Returns the full url containing host, page and anchor for the given element



285
286
287
# File 'app/helpers/alchemy/elements_helper.rb', line 285

def full_url_for_element(element)
  "#{current_server}/#{element.page.urlname}##{element_dom_id(element)}"
end

- (Object) render_cell_elements(cell)

Renders all element partials from given cell.



262
263
264
265
# File 'app/helpers/alchemy/elements_helper.rb', line 262

def render_cell_elements(cell)
  return warning("No cell given.") if cell.blank?
  render_elements({:from_cell => cell})
end

- (Object) render_element(element, part = :view, options = {}, counter = 1)

Note:

If the view partial is not found alchemy/elements/_view_not_found.html.erb or alchemy/elements/_editor_not_found.html.erb gets rendered.

This helper renders a Alchemy::Element partial.

A element has always two partials:

  1. A view partial (This is the view presented to the website visitor)

  2. A editor partial (This is the form presented to the website editor while in page edit mode)

The partials are located in app/views/alchemy/elements.

View partial naming

The partials have to be named after the name of the element as defined in the elements.yml file and has to be suffixed with the partial part.

Example

Given a headline element

# elements.yml
- name: headline
  contents:
  - name: text
    type: EssenceText

Then your element view partials has to be named like:

app/views/alchemy/elements/_headline_editor.html.erb
app/views/alchemy/elements/_headline_view.html.erb

Element partials generator

You can use this handy generator to let Alchemy generate the partials for you:

$ rails generate alchemy:elements --skip

Usage

<%= render_element(Alchemy::Element.published.named(:headline).first) %>

Parameters:

  • element (Alchemy::Element)

    The element you want to render the view for

  • part (Symbol) (defaults to: :view)

    The type of element partial (:editor or :view) you want to render

  • options (Hash) (defaults to: {})

    Additional options

  • counter (Number) (defaults to: 1)

    a counter



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'app/helpers/alchemy/elements_helper.rb', line 173

def render_element(element, part = :view, options = {}, counter = 1)
  begin
    if element.blank?
      warning('Element is nil')
      render :partial => "alchemy/elements/#{part}_not_found", :locals => {:name => 'nil'}
    else
      element.store_page(@page) if part == :view
      locals = options.delete(:locals)
      render(
        :partial => "alchemy/elements/#{element.name.underscore}_#{part}",
        :locals => {
          :element => element,
          :counter => counter,
          :options => options
        }.merge(locals || {})
      )
    end
  rescue ActionView::MissingTemplate => e
    warning(%(
      Element #{part} partial not found for #{element.name}.\n
      #{e}
    ))
    render :partial => "alchemy/elements/#{part}_not_found", :locals => {:name => element.name, :error => "Element #{part} partial not found.<br>Use <code>rails generate alchemy:elements</code> to generate it."}
  end
end

- (Object) render_elements(options = {})

Renders all elements from current page

Examples:

Render only certain elements:

<header>
  <%= render_elements only: ['header', 'claim'] %>
</header>
<section id="content">
  <%= render_elements except: ['header', 'claim'] %>
</section>

Render elements from global page:

<footer>
  <%= render_elements from_page: 'footer' %>
</footer>

Render elements from cell:

<aside>
  <%= render_elements from_cell: 'sidebar' %>
</aside>

Fallback to elements from global page:

You can use the fallback option as an override for elements that are stored on another page. So you can take elements from a global page and only if the user adds an element on current page the local one gets rendered.

  1. You have to pass the the name of the element the fallback is for as for key.

  2. You have to pass a page_layout name or Page from where the fallback elements is taken from as from key.

  3. You can pass the name of element to fallback with as with key. This is optional (the element name from the for key is taken as default).

<%= render_elements(fallback: {
  for: 'contact_teaser',
  from: 'sidebar',
  with: 'contact_teaser'
}) %>

Parameters:

  • options (Hash) (defaults to: {})

    Additional options.

Options Hash (options):

  • :count (Number)

    The amount of elements to be rendered (begins with first element found)

  • :except (Array or String) — default: []

    A list of element names not to be rendered.

  • :fallback (Hash)

    Define elements that are rendered from another page.

  • :from_cell (Alchemy::Cell or String)

    The cell the elements are rendered from. You can pass a Cell name String or a Cell object.

  • :from_page (Alchemy::Page or String) — default: @page

    The page the elements are rendered from. You can pass a page_layout String or a Page object.

  • :only (Array or String) — default: []

    A list of element names only to be rendered.

  • :random (Boolean)

    Randomize the output of elements

  • :reverse (Boolean)

    Reverse the rendering order

  • :sort_by (String)

    The name of a Content to sort the elements by



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'app/helpers/alchemy/elements_helper.rb', line 74

def render_elements(options = {})
  default_options = {
    :except => [],
    :only => [],
    :from_page => @page,
    :from_cell => nil,
    :count => nil,
    :offset => nil,
    :locals => {},
    :render_format => "html",
    :fallback => nil
  }
  options = default_options.merge(options)
  if options[:from_page].class == Page
    page = options[:from_page]
  else
    page = Page.where(:page_layout => options[:from_page]).with_language(session[:language_id]).all
  end
  if page.blank?
    warning('Page is nil')
    return ""
  else
    if page.class == Array
      all_elements = page.collect { |p| p.find_elements(options) }.flatten
    else
      all_elements = page.find_elements(options)
    end
    if options[:sort_by].present?
      all_elements = all_elements.sort_by { |e| e.contents.detect { |c| c.name == options[:sort_by] }.ingredient }
    end
    element_string = ""
    if options[:fallback]
      if all_elements.detect { |e| e.name == options[:fallback][:for] }.blank?
        if options[:fallback][:from].class.name == 'Alchemy::Page'
          from = options[:fallback][:from]
        else
          from = Page.not_restricted.where(:page_layout => options[:fallback][:from]).with_language(session[:language_id]).first
        end
        if from
          all_elements += from.elements.named(options[:fallback][:with].blank? ? options[:fallback][:for] : options[:fallback][:with])
        end
      end
    end
    all_elements.each_with_index do |element, i|
      element_string += render_element(element, :view, options, i+1)
    end
    element_string.html_safe
  end
end