module Insightful module NavigationHelper # - menu(c(:menu)) do |attributes, node| # - attributes[:class] = "one two" # - node[:title] def menu(nodes, options = {}, &block) menu_builder(nodes, 0, options, &block) end def nested_set_menu(clazz, options = {}, &block) menu(simple_nested_set(clazz), options) do |node, children, level| if block_given? case block.arity when 1 yield node[:node] when 2 yield node[:node], children when 3 yield node[:node], children, level end end end end def menu_builder(nodes, level = 0, options = {}, &block) return "" if nodes.empty? menu_attributes = options[:menu_attributes] if options.has_key?(:menu_attributes) options.delete(:menu_attributes) haml_tag :ul, menu_attributes do nodes.each_with_index do |node, i| # set the attributes attributes = options[:li_attributes].blank? ? {} : options[:li_attributes].dup attributes[:class] ||= "" if i == 0 and options.has_key?(:first) attributes[:class] << " #{options[:first]}".squeeze(" ") elsif i == nodes.length - 1 and options.has_key?(:last) attributes[:class] << " #{options[:last]}".squeeze(" ") end haml_tag :li, attributes do children = nil if node.has_key?(:children) children = node[:children] elsif node.respond_to?(:children) children = node.children end if block_given? case block.arity when 1 yield node when 2 yield node, children when 3 yield node, children, level end end # pass it in again menu_builder(children, level + 1, options, &block) unless children.empty? end end end end def simple_nested_set(clazz) # Post for example stack = [] # Post for example result = [] clazz.all(:order => "lft").each do |node| if stack.empty? stack.push({:node => node, :children => []}) result << stack.last next end if stack.last[:node].lft < node.lft && node.lft < stack.last[:node].rgt child = {:node => node, :children => []} stack.last[:children] << child unless node.leaf? # (node.rgt - node.lft == 1) stack.push(child) end if node.rgt + 1 == stack.last[:node].rgt stack.pop end else stack.pop end end result end def breadcrumb(item, options = {}, &block) options[:from] ||= "/" + item.url.gsub(/^\//, "").split("/").first options[:to] ||= item.url breadcrumb_builder(options[:from], options, &block) end def breadcrumb_builder(current_url, options, &block) item = site.find_by_url(current_url) return "" unless item haml_tag :a, options.merge(:href => current_url) do if block_given? yield item else haml_concat item.title end end if options[:to] != current_url haml_concat options[:delimiter] || " ยป " next_node = options[:to].gsub(/#{current_url}\/?/, "").split("/").first breadcrumb_builder("#{current_url}/#{next_node}", options, &block) end end end end