4

I'm trying to use Zurb foundation to style an app built with the latest version of refinery. I began by following this guide

http://blog.flatironschool.com/post/54511602806/build-a-blog-based-site-with-refinerycms

but the latest version of refinery uses "menu-presenter" to layout the menu.

I have got this far:

module ApplicationHelper


   def zurb_menu
      menu_items = Refinery::Menu.new(Refinery::Page.in_menu)

      presenter = Refinery::Pages::MenuPresenter.new(menu_items, self)
      presenter.css = "top-bar-section"
      presenter.dom_id = nil
      presenter.menu_tag = :section
      presenter.list_tag = "ul class='left'"
      presenter
   end
end

This sort of works, However the elements aren't quite right and the main problem is that the I don't know how or where to add the dropdown class to make the child elements dropdown. With the code above the child elements are just expanded all the time.

Thanks for your help

TimK
  • 109
  • 1
  • 9
  • Hi TimK, I've tried working a bit with Bootstrap and RefineryCMS and found it quite awkward to get styles working. I'm looking right now at Zurb and if I get this menu working I'll post an answer here. My guess is you/we will need to modify the MenuPresenter, see http://stackoverflow.com/questions/14759712/rails-bootstrap-navbar-and-refinerycms -- about the 4th answer down is for Refinery 2.1.0 (we don't have _menu or _menu_branch partials any more) – CJBrew Nov 19 '13 at 23:47
  • I have now got a sample nav in Zurb working, using a _header.erb.html override that basically mirrors what I found at http://foundation.zurb.com/docs/components/top-bar.html. Looks OK but I don't understand the hidden menu / responsive thing yet. I think to get dropdowns working you may have some luck with the code for Bootstrap as posted in my comment above. – CJBrew Nov 20 '13 at 00:35
  • If you can explain what it is you're trying to achieve, I or someone else may be able to help... – CJBrew Nov 20 '13 at 00:38
  • No need to explain, I think I've just hit exactly the same problem. The sub-menu items are permanently expanded. Also, the menu doesn't appear to expand-on-click like it should -- are you seeing this also? Possibly the same issue as http://stackoverflow.com/questions/14392108/foundation-responsive-top-bar-toggle-not-working-in-rails-3-2-8-project/20085501#20085501 (I found a workaround - my answer there - but on my site, on-click the whole tree of items is shown without any hierarchy.) – CJBrew Nov 20 '13 at 01:21
  • Hi @CJBrew - thanks for looking at this! I think you have discovered what i meant but just in case here is the link to where I'm at the moment http://edmanual.herokuapp.com/test. I think you're right the menu presenter needs to modified to apply the right has-dropdown and dropdown classes in the appropriate places but I can't figure out how to do it and have been trying for hours - let me know if you get anywhere – TimK Nov 20 '13 at 15:18

3 Answers3

3

instead of in_menu if you use fast_menu, then you will be able to reorder pages. menu_pages works, but you it will not render pages in the same order as they are in admin. hope this helps someone.

menu_items = Refinery::Menu.new(Refinery::Page.menu_pages)

menu_items = Refinery::Menu.new(Refinery::Page.fast_menu)

bubb
  • 599
  • 4
  • 3
  • For what it's worth I found `in_menu` is in the wrong order and I had to write a line of code to reverse it... I'll take a look at fast_menu, thanks – CJBrew Dec 02 '13 at 10:08
  • **fast_menu** is optimised scope containing only live pages ordered for display in a menu. this is what it is defined in refinerycms-pages 2.1.1 version. def fast_menu live.in_menu.order(arel_table[:lft]).includes(:parent, :translations) end – bubb Dec 02 '13 at 10:26
  • correction: in_menu shows in the correct order on Heroku but in reverse on my test site!... very strange. – CJBrew Dec 11 '13 at 20:51
2

This is my version... Tested; and it works for me at least.

I used the code for Bootstrap I found on another question (link in the comments above). But instead of replacing the entire menu presenter I override only the methods we need for this.

Create a Zurb menu presenter file:

app/presenters/refinery/pages/zurb_menu_presenter.rb

module Refinery
  module Pages
    class ZurbMenuPresenter < MenuPresenter

    config_accessor :list_dropdown_css, :list_item_dropdown_css, :list_first_css

    MenuPresenter.menu_tag = :section
    MenuPresenter.css = "top-bar-section"
    self.list_dropdown_css = "dropdown"
    self.list_item_dropdown_css = "has-dropdown"
    self.list_first_css = nil

      def render_menu_items(menu_items)
        if menu_items.present?
          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
      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 = []

        css << list_first_css if (roots == menu_items)
        css << list_dropdown_css if (roots != menu_items)

        css.reject(&:blank?).presence

      end


      def menu_item_css(menu_item, index)
        css = []

        css << list_item_dropdown_css if (check_for_dropdown_item(menu_item))
        css << selected_css if selected_item_or_descendant_item_selected?(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)

          if check_for_dropdown_item(menu_item)
              menu_item_class = list_item_dropdown_css
          else
              menu_item_class =  menu_item_css(menu_item, index)
          end

          content_tag(list_item_tag, :class => menu_item_class) 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

I have a helper in app/helpers/application_helpers.rb:

module ApplicationHelper
    def zurb_menu
        menu_items = Refinery::Menu.new(Refinery::Page.menu_pages)
        presenter = Refinery::Pages::ZurbMenuPresenter.new(menu_items, self)
        presenter
    end
...

Then just call zurb_menu from the _header. I'm doing the Navbar stuff explicitly in my header function, which may or may not be right; you could roll that into the ZurbMenuPresenter class, and I may well do so:

app/views/refinery/_header.html.erb

<nav class="top-bar hide-for-small">
<ul class="title-area">

    <li class="name">
    <h1><a href="/">Home</a></h1>
    </li>
    <li class="toggle-topbar menu-icon"><a href="#"><span>Menu</span></a></li>
</ul>
<script src="http://foundation.zurb.com/public/assets/marketing_docs.js"></script>
<%=
    zurb_menu.to_html
%>

</nav>
CJBrew
  • 2,720
  • 1
  • 20
  • 27
  • I don't have the reputation to upvote this answer but it worked for me . With the following minor modification. 1. In the application helper I needed **menu_items = Refinery::Menu.new(Refinery::Page.in_menu)** not .menu_pages. 2. I needed to put the _header code in my application layout file between the body tags. Thanks @ghoppe for the input – TimK Nov 21 '13 at 09:25
  • Thanks @TimK. Have you the 'rep' to be able to mark it as the answer? :) As for "in_menu" -- I saw that in your original post and wondered what it was. I think I may have created a helper that provides "menu_pages". Whatever works for you. – CJBrew Nov 21 '13 at 17:33
  • Perfect Solution! I just had to add data-topbar to the nav element. :) – Dan Mitchell Dec 18 '13 at 14:27
  • 1
    I've tweaked this solution so that `zurb_menu` can be passed a variety of menu items and html/css options. As a result, it works in any partial, not just the header. See the [step-by-step post](http://blog.milkfarmproductions.com/post/73806803072/refinery-cms-and-zurb-foundation) or the [github repository](https://github.com/milkfarm/refinery-foundation). – milkfarm Jan 19 '14 at 18:01
0

You'll need to override the MenuPresenter. Specifically, you'll need to add the appropriate classes to the children of the top-level menu with the render_menu_item function. I'm not too familiar with Zerb Foundation, but this should get you started.

Note: untested code, I just switched in some class names from my own Bootstrap menu solution to get you started, you might have to do a bit more work. I'm also adding your helper code to the overridden presenter, so you can just call it in a view like this: <%= Refinery::ZerbMenuPresenter.new(refinery_menu_pages, self).to_html %>

app/presenters/refinery/zerb_menu_presenter.rb

module Refinery
  class ZerbMenuPresenter < ::Refinery::MenuPresenter
    self.css = "top-bar-section"
    self.dom_id = nil
    self.menu_tag = :section
    self.list_tag = "ul class='left'"
    def render_menu_item(menu_item, index)
      content_tag(list_item_tag, :class => menu_item_css(menu_item, index)) do
        buffer = ActiveSupport::SafeBuffer.new
        if menu_item_children(menu_item).present?
          buffer << link_to("#{menu_item.title}", context.refinery.url_for(menu_item.url), :class => 'has-dropdown')
          buffer << render_menu_items(menu_item_children(menu_item), 'dropdown')
        else
          buffer << link_to(menu_item.title, context.refinery.url_for(menu_item.url))
        end
        buffer
      end
    end
  end
end
ghoppe
  • 21,452
  • 3
  • 30
  • 21