module SimpleNavigation # View helpers to render the navigation. # # Use render_navigation as following to render your navigation: # * call render_navigation without :level option to render your # complete navigation as nested tree. # * call render_navigation(level: x) to render a specific # navigation level (e.g. level: 1 to render your primary navigation, # level: 2 to render the sub navigation and so forth) # * call render_navigation(:level => 2..3) to render navigation # levels 2 and 3). # # For example, you could use render_navigation(level: 1) to render your # primary navigation as tabs and render_navigation(level: 2..3) to render # the rest of the navigation as a tree in a sidebar. # # ==== Examples (using Haml) # #primary_navigation= render_navigation(level: 1) # # #sub_navigation= render_navigation(level: 2) # # #nested_navigation= render_navigation # # #top_navigation= render_navigation(level: 1..2) # #sidebar_navigation= render_navigation(level: 3) module Helpers def self.load_config(options, includer, &block) context = options.delete(:context) SimpleNavigation.init_adapter_from includer SimpleNavigation.load_config context SimpleNavigation::Configuration.eval_config context if block_given? || options[:items] SimpleNavigation.config.items(options[:items], &block) end unless SimpleNavigation.primary_navigation fail 'no primary navigation defined, either use a navigation config ' \ 'file or pass items directly to render_navigation' end end def self.apply_defaults(options) options[:level] = options.delete(:levels) if options[:levels] { context: :default, level: :all }.merge(options) end # Renders the navigation according to the specified options-hash. # # The following options are supported: # * :level - defaults to :all which renders the the sub_navigation # for an active primary_navigation inside that active # primary_navigation item. # Specify a specific level to only render that level of navigation # (e.g. level: 1 for primary_navigation, etc). # Specifiy a Range of levels to render only those specific levels # (e.g. level: 1..2 to render both your first and second levels, maybe # you want to render your third level somewhere else on the page) # * :expand_all - defaults to false. If set to true the all # specified levels will be rendered as a fully expanded # tree (always open). This is useful for javascript menus like Superfish. # * :context - specifies the context for which you would render # the navigation. Defaults to :default which loads the default # navigation.rb (i.e. config/navigation.rb). # If you specify a context then the plugin tries to load the configuration # file for that context, e.g. if you call # render_navigation(context: :admin) the file # config/admin_navigation.rb will be loaded and used for rendering # the navigation. # * :items - you can specify the items directly (e.g. if items are # dynamically generated from database). # See SimpleNavigation::ItemsProvider for documentation on what to # provide as items. # * :renderer - specify the renderer to be used for rendering the # navigation. Either provide the Class or a symbol matching a registered # renderer. Defaults to :list (html list renderer). # # Instead of using the :items option, a block can be passed to # specify the items dynamically # # ==== Examples # render_navigation do |menu| # menu.item :posts, "Posts", posts_path # end # def render_navigation(options = {}, &block) container = active_navigation_item_container(options, &block) container && container.render(options) end # Returns the name of the currently active navigation item belonging to the # specified level. # # See Helpers#active_navigation_item for supported options. # # Returns an empty string if no active item can be found for the specified # options def active_navigation_item_name(options = {}) active_navigation_item(options, '') do |item| item.name(apply_generator: false) end end # Returns the key of the currently active navigation item belonging to the # specified level. # # See Helpers#active_navigation_item for supported options. # # Returns nil if no active item can be found for the specified # options def active_navigation_item_key(options = {}) active_navigation_item(options, &:key) end # Returns the currently active navigation item belonging to the specified # level. # # The following options are supported: # * :level - defaults to :all which returns the # most specific/deepest selected item (the leaf). # Specify a specific level to only look for the selected item in the # specified level of navigation # (e.g. level: 1 for primary_navigation, etc). # * :context - specifies the context for which you would like to # find the active navigation item. Defaults to :default which loads the # default navigation.rb (i.e. config/navigation.rb). # If you specify a context then the plugin tries to load the configuration # file for that context, e.g. if you call # active_navigation_item_name(context: :admin) the file # config/admin_navigation.rb will be loaded and used for searching the # active item. # * :items - you can specify the items directly (e.g. if items are # dynamically generated from database). # See SimpleNavigation::ItemsProvider for documentation on what to provide # as items. # # Returns the supplied value_for_nil object (nil # by default) if no active item can be found for the specified # options def active_navigation_item(options = {}, value_for_nil = nil) if options[:level].nil? || options[:level] == :all options[:level] = :leaves end container = active_navigation_item_container(options) if container && (item = container.selected_item) block_given? ? yield(item) : item else value_for_nil end end # Returns the currently active item container belonging to the specified # level. # # The following options are supported: # * :level - defaults to :all which returns the # least specific/shallowest selected item. # Specify a specific level to only look for the selected item in the # specified level of navigation # (e.g. level: 1 for primary_navigation, etc). # * :context - specifies the context for which you would like to # find the active navigation item. Defaults to :default which loads the # default navigation.rb (i.e. config/navigation.rb). # If you specify a context then the plugin tries to load the configuration # file for that context, e.g. if you call # active_navigation_item_name(context: :admin) the file # config/admin_navigation.rb will be loaded and used for searching the # active item. # * :items - you can specify the items directly (e.g. if items are # dynamically generated from database). # See SimpleNavigation::ItemsProvider for documentation on what to provide # as items. # # Returns nil if no active item container can be found def active_navigation_item_container(options = {}, &block) options = SimpleNavigation::Helpers.apply_defaults(options) SimpleNavigation::Helpers.load_config(options, self, &block) SimpleNavigation.active_item_container_for(options[:level]) end end end