Module: Cms::MenuHelper
- Defined in:
- app/helpers/cms/menu_helper.rb
Instance Method Summary collapse
-
#menu_items(options = {}) ⇒ Object
This will render generate an array-of-hashes tree structure based on the page, which can be passed to render_menu in order to generate a menu.
-
#render_menu(options = {}) ⇒ Object
Renders a menu.
Instance Method Details
#menu_items(options = {}) ⇒ Object
This will render generate an array-of-hashes tree structure based on the page, which can be passed to render_menu in order to generate a menu.
With no options passed, it will generate a structure that includes all the child sections of the root and then it will include the path of decendent sections all the way to the current page.
Hidden pages will not be included, but if the first page in a Section is hidden, it will be used as the URL for that Section. This is commonly done to have a page for a Section and avoid having duplicates in the navigation.
You can change the behavior with the following options, all of these are optional:
Options
-
:page
- What page should be used as the current page. If this value is omitted, the value in @page will be used. -
:path
- This will be used to look up a section and that section will used to generate the menu structure. The current page will still be the value of the page option or @page. Note that this is the path to a section, not a path to a page. -
:from_top
- How many below levels from the root the tree should start at.All sections at this level will be shown. The default is 0, which means show all nodes that are direct children of the root
-
:depth
- How many levels deep should the tree go, relative to from_top.If no value is supplied, the tree will go all the way down to the current page. If a value is supplied, the tree will be that many levels underneath from_top deep.
-
:limit
- Limits the number of top-level elements that will be included in the list -
:show_all_siblings
- Passing true for this option will make all sibilings appear in the tree. The default is false, in which case only the siblings of nodes within the open path will appear.
Examples
Assume you have the structure the NFL, which is NFL > Conference > Division > Team, with teams being a Page, everything else a Section. Also, assume we are on the Baltimore Ravens page. If you’re not a footbal fan, see sports.yahoo.com/nfl/teams
menu_items
# => [
{ :id => "section_2", :url => "/buf", :name => "AFC", :children => [
{ :id => "section_3", :url => "/buf", :name => "East" },
{ :id => "section_4", :url => "/bal", :name => "North", :children => [
{ :id => "page_5", :selected => true, :url => "/bal", :name => "Baltimore Ravens" },
{ :id => "page_6", :url => "/cin", :name => "Cincinnati Bengals" },
{ :id => "page_7", :url => "/cle", :name => "Cleveland Browns" },
{ :id => "page_8", :url => "/pit", :name => "Pittsburgh Steelers" }
] },
{ :id => "section_9", :url => "/hou", :name => "South" },
{ :id => "section_10}", :url => "/den", :name => "West" }
] },
{ :id => "section_11", :url => "/dal", :name => "NFC" }
]
menu_items(:depth => 2, :show_all_siblings => true)
# => [
{ :id => "section_2", :url => "/buf", :name => "AFC", :children => [
{ :id => "section_3", :url => "/buf", :name => "East" },
{ :id => "section_4", :url => "/bal", :name => "North" },
{ :id => "section_5", :url => "/hou", :name => "South" },
{ :id => "section_6", :url => "/den", :name => "West" }
] },
{ :id => "section_7", :url => "/dal", :name => "NFC", :children => [
{ :id => "section_8", :url => "/dal", :name => "East" },
{ :id => "section_9", :url => "/chi", :name => "North" },
{ :id => "section_10", :url => "/atl", :name => "South" },
{ :id => "section_11", :url => "/ari", :name => "West" }
] }
]
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'app/helpers/cms/menu_helper.rb', line 106 def ( = {}) # Intialize parameters selected_page = [:page] || @page return nil unless selected_page # Path to the section if .has_key?(:path) section_for_path = Section.find_by_path([:path]) raise "Could not find section for path '#{[:path]}'" unless section_for_path ancestors = section_for_path.ancestors(:include_self => true) else ancestors = selected_page.ancestors end if .has_key?(:from_top) ancestors = ancestors[[:from_top].to_i..-1] || [] end depth = .has_key?(:depth) ? [:depth].to_i : 1.0/0 show_all_siblings = [:show_all_siblings] || false # We are defining a recursive lambda that takes the top-level sections fn = lambda do |section_nodes, current_depth| section_nodes.map do |section_node| node = section_node.node item = {} item[:id] = "#{section_node.node_type.gsub("::","_").underscore}_#{section_node.node_id}" # If we are showing a section item, we want to use the path for the first page page_or_link = section_node.section? ? node.first_page_or_link : node if section_node.section? && page_or_link item[:selected] = true if page_or_link.respond_to?(:hidden?) && page_or_link.hidden? && selected_page == page_or_link else item[:selected] = true if selected_page == page_or_link end item[:url] = page_or_link.try(:path) || '#' item[:name] = node.name item[:target] = "_blank" if page_or_link.respond_to?(:new_window?) && page_or_link.new_window? # Now if this is a section, we do the child nodes, # but only if the show_all_siblings parameter is true, # or if this section is one of the current page's ancestors # and also if the current depth is less than the target depth if section_node.section? && current_depth < depth && (show_all_siblings || ancestors.include?(node)) && !node.visible_child_nodes.empty? item[:children] = fn.call(node.visible_child_nodes, current_depth + 1) end item end end if ancestors.empty? [] else fn.call(ancestors.first.visible_child_nodes(:limit => [:limit]), 1) end end |
#render_menu(options = {}) ⇒ Object
Renders a menu. There are two options, neither are required:
Options
-
:items
- The items which should appear in the menu. This defaults to calling menu_items which generates items automatically based on the current page. But you can use this option to pass in a custom menu structure. -
:partial
- The partial used to render the menu. By default this is “partials/menu”, which can be customised through the CMS. The partial gets a local variableitems
.
Structure of items
The items should be an array of hashes, in a tree. Each hash can have the following keys (name and url are required, others are optional):
-
:name
- The name which appears in the menu -
:url
- The URL to link to -
:id
- The id for the menu item -
:selected
- Boolean value to indicate whether the menu item is the current page -
:target
- The target attribute for the link -
:children
- An array of hashes containing the child menu items. This is where the tree structure comes in.
Edge Cases:
If both @page and :items are nil/empty, this will return an empty string. This might happen if used on an CMS
rendered page, where @page isn't set.
29 30 31 32 33 34 35 36 37 |
# File 'app/helpers/cms/menu_helper.rb', line 29 def ( = {}) [:items] ||= () return "" unless [:items] [:partial] ||= "cms/menus/menu" [:id] ||= "menu" [:class] ||= "menu" render :partial => [:partial], :locals => { :items => [:items], :css_id => [:id], :css_class => [:class] } end |