Changing Menu Markup with a Menu Presenter

Popular web frameworks like Twitter Bootstrap and Zurb Foundation require specific markup to implement navigation elements.

Here we will implement a simple navigation bar with markup for Foundation.

Setup

Override the refinery file which creates the menu, and replace it with the following code

rake refinery:override view=refinery/_header.html

#/app/views/refinery/shared/_header.html.erb
...
<section class="top-bar-section" id="menu">
  <%= foundation_menu(refinery_menu_pages, list_tag_css: 'left').to_html %>
  <ul class='right'>
    <li> <a href="/contact">Contact Us</a></li>
  </ul>
</section>

Next an application helper.

bc.. #app/helpers/ApplicationHelper Module ApplicationHelper

  1. Creates a dropdown menu with items matching Refinery pages
  2. and tags/css matching Foundation markup #
  3. Options:
  4. * :menu_tag – A wrapper for the lists
  5. * :dom_id – The dom id for the wrapper
  6. * :css – The css class for the wrapper
  7. * :list_dropdown_css – The css class of the submenu list
  8. * :list_item_dropdown_css – The css class of the main menu item that has a dropdown
  9. * :list_tag_css – The css class of the main menu
  10. * :active_css – The css class denoting a active menu item
  11. * :selected_css – The css class denoting a current menu item def foundation_menu(items, options = {}) presenter = Refinery::Pages::FoundationMenuPresenter.new(items, self) %w(menu_tag dom_id css list_dropdown_css list_item_dropdown_css list_tag_css active_css selected_css).map(&:to_sym).each do |k| presenter.send(“#{k}=”, options[k]) if options.has_key?(k) end presenter end end

And finally the menu presenter.

bc..

  1. app/presenters/zurb_menu_presenter.rb module Refinery module Pages class FoundationMenuPresenter < MenuPresenter
config_accessor :list_dropdown_css, :list_item_dropdown_css, :list_tag_css self.menu_tag = nil self.dom_id = nil self.css = nil self.list_dropdown_css = ‘dropdown’ self.list_item_dropdown_css = ‘has-dropdown’ self.list_tag_css = nil self.active_css = ‘active’ self.selected_css = ‘active’ private def render_menu(items) if menu_tag content_tag(menu_tag, :id => dom_id, :class => css) do render_menu_items(items) end else render_menu_items(items) end end def render_menu_items(menu_items) return if menu_items.blank? content_tag(list_tag, :class => menu_items_css(menu_items)) do menu_items.each_with_index.inject(ActiveSupport::SafeBuffer.new) do |buffer, (item, index)| buffer << render_menu_item(item, index) end end end def check_for_dropdown_item(menu_item) ( menu_item != roots.first ) && ( menu_item_children( menu_item ).count > 0 ) end def menu_items_css(menu_items) css = [] if roots == menu_items css << list_tag_css else css << list_dropdown_css end css.reject(&:blank?).presence end def menu_item_css(menu_item, index) css = [] css << active_css if descendant_item_selected?(menu_item) css << selected_css if selected_item?(menu_item) css << list_item_dropdown_css if check_for_dropdown_item(menu_item) css << first_css if index == 0 css << last_css if index == menu_item.shown_siblings.length css.reject(&:blank?).presence end def render_menu_item(menu_item, index) content_tag(list_item_tag, :class => menu_item_css(menu_item, index)) do @cont = context.refinery.url_for(menu_item.url) buffer = ActiveSupport::SafeBuffer.new buffer << link_to(menu_item.title, context.refinery.url_for(menu_item.url)) buffer << render_menu_items(menu_item_children(menu_item)) buffer end end end end

end

Thanks Many thanks to Moo the blog’s post which is what I used to get started.