RefineryCMS:将引导样式应用于导航菜单

我已将Refinery CMS升级到最新版本(2.1.0),其中有一种渲染导航菜单的新方法:

(在部分_header.html.erb

  

相同部分的旧版本:

  "/refinery/menu", :locals => { :dom_id => 'menu', :css => 'menu' }) %> 

如何使用MenuPresenter将导航样式添加到导航栏?

它可以完成,但解决方案并不漂亮,因为Refinery 2.1中的Menu Presenter不支持开箱即用的所有正确的CSS选项。 但有点坚持不懈,这大致是做什么的:

首先,在这里创建一个新的空白文件: config/initializers/refinery/monkey_patch_menu_presenter.rb

在此补丁文件中,粘贴菜单展示器的更新版本(2013年10月发布)的内容: menu_presenter.rb

接下来,根据菜单演示者指南第5节中的说明 ,在app/helpers/application_helper.rb文件中,添加一个名为navigation_menu的新方法:

 def navigation_menu presenter = Refinery::Pages::MenuPresenter.new(refinery_menu_pages, self) presenter.css = "navbar-inner" presenter.menu_tag = :div presenter.list_tag_css = "nav" presenter.selected_css = "active" presenter.first_css = "" presenter.last_css = "" presenter.max_depth = 0 # prevents dropdown menus, which don't render correctly presenter end 

最后,在你的app/views/refinery/_header.html.erb文件中(使用$ bundle exec rake refinery:override view=refinery/_header如果它不存在),替换为:

 <%= Refinery::Pages::MenuPresenter.new(refinery_menu_pages, self).to_html %> 

有:

  

确保已加载Bootstrap CSS / JS文件并将整个页面包装在

元素中。 然后重新启动应用程序以使修补程序生效,希望您能看到熟悉的引导程序导航栏。

祝好运!

马丁。

这里有一个上面的menu_presenter.rb版本,它也可以呈现子菜单(如果是Bootstrap 3,则为RefineryCMS 2.1.1):

 require 'active_support/core_ext/string' require 'active_support/configurable' require 'action_view/helpers/tag_helper' require 'action_view/helpers/url_helper' module Refinery module Pages class MenuPresenter include ActionView::Helpers::TagHelper include ActionView::Helpers::UrlHelper include ActiveSupport::Configurable config_accessor :roots, :menu_tag, :list_tag, :list_item_tag, :css, :dom_id, :max_depth, :selected_css, :first_css, :last_css, :list_tag_css, :link_tag_css self.dom_id = 'menu' self.css = "collapse navbar-collapse" self.menu_tag = :div self.list_tag = :ul self.list_item_tag = :li self.selected_css = 'active' self.first_css = :first self.last_css = :last self.list_tag_css = "nav navbar-nav" def roots config.roots.presence || collection.roots end attr_accessor :context, :collection delegate :output_buffer, :output_buffer=, :to => :context def initialize(collection, context) @collection = collection @context = context end def to_html render_menu(roots) if roots.present? end private def render_menu(items) content_tag(menu_tag, :id => dom_id, :class => css) do render_menu_items(items) end end def render_menu_items(menu_items) if menu_items.present? content_tag(list_tag, :class => list_tag_css) 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 render_menu_items_children(menu_items) if menu_items.present? content_tag(list_tag, :class => 'dropdown-menu') 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 render_menu_item_link_dropdown(menu_item) link_to( menu_item.title, context.refinery.url_for(menu_item.url), class: "dropdown-toggle", data: {toggle:"dropdown", target: "#"}) end def render_menu_item_link(menu_item) link_to(menu_item.title, context.refinery.url_for(menu_item.url), :class => link_tag_css) end def render_menu_item(menu_item, index) content_tag(list_item_tag, :class => menu_item_css(menu_item, index)) do buffer = ActiveSupport::SafeBuffer.new # Check for sub menu menu_item_children(menu_item).empty? ? buffer << render_menu_item_link(menu_item) : buffer << render_menu_item_link_dropdown(menu_item) buffer << render_menu_items_children(menu_item_children(menu_item)) buffer end end # Determines whether any item underneath the supplied item is the current item according to rails. # Just calls selected_item? for each descendant of the supplied item # unless it first quickly determines that there are no descendants. def descendant_item_selected?(item) item.has_children? && item.descendants.any?(&method(:selected_item?)) end def selected_item_or_descendant_item_selected?(item) selected_item?(item) || descendant_item_selected?(item) end # Determine whether the supplied item is the currently open item according to Refinery. def selected_item?(item) path = context.request.path path = path.force_encoding('utf-8') if path.respond_to?(:force_encoding) # Ensure we match the path without the locale, if present. if %r{^/#{::I18n.locale}/} === path path = path.split(%r{^/#{::I18n.locale}}).last.presence || "/" end # First try to match against a "menu match" value, if available. return true if item.try(:menu_match).present? && path =~ Regexp.new(item.menu_match) # Find the first url that is a string. url = [item.url] url << ['', item.url[:path]].compact.flatten.join('/') if item.url.respond_to?(:keys) url = url.last.match(%r{^/#{::I18n.locale.to_s}(/.*)}) ? $1 : url.detect{|u| u.is_a?(String)} # Now use all possible vectors to try to find a valid match [path, URI.decode(path)].include?(url) || path == "/#{item.original_id}" end def menu_item_css(menu_item, index) css = [] css << selected_css if selected_item_or_descendant_item_selected?(menu_item) css << "dropdown" unless menu_item_children(menu_item).empty? css << first_css if index == 0 css << last_css if index == menu_item.shown_siblings.length css.reject(&:blank?).presence end def menu_item_children(menu_item) within_max_depth?(menu_item) ? menu_item.children : [] end def within_max_depth?(menu_item) !max_depth || menu_item.depth < max_depth end end end end