|
module Menu
|
|
|
|
class Node
|
|
include Enumerable
|
|
attr_accessor :parent
|
|
attr_reader :name
|
|
|
|
def initialize(name, children = [])
|
|
@name = name
|
|
@children = children
|
|
@last_items_count = children.size
|
|
end
|
|
|
|
def caption
|
|
case @caption
|
|
when String
|
|
@caption
|
|
when Proc
|
|
@caption.call().to_s
|
|
when Symbol
|
|
@caption.to_s.humanize
|
|
else
|
|
@name.to_s.humanize unless @name == :divider
|
|
end
|
|
end
|
|
|
|
def authorized_children
|
|
children.map{|sub_item| sub_item if sub_item.authorized?}.compact
|
|
end
|
|
|
|
def children
|
|
if block_given?
|
|
@children.each {|child| yield child}
|
|
else
|
|
@children
|
|
end
|
|
end
|
|
|
|
# Returns the number of descendants + 1
|
|
def size
|
|
@children.inject(1) {|sum, node| sum + node.size}
|
|
end
|
|
|
|
def each &block
|
|
yield self
|
|
children { |child| child.each(&block) }
|
|
end
|
|
|
|
# Adds a child at first position
|
|
def prepend(child)
|
|
add_at(child, 0)
|
|
end
|
|
|
|
# Adds a child at given position
|
|
def add_at(child, position)
|
|
if child.is_a?(Menu::Item) && find {|node| node.name == child.name}
|
|
Rails.logger.error "Child already exists #{child.name}"
|
|
return
|
|
end
|
|
|
|
@children = @children.insert(position, child)
|
|
child.parent = self
|
|
child
|
|
end
|
|
|
|
# Adds a child as last child
|
|
def add_last(child)
|
|
add_at(child, -1)
|
|
@last_items_count += 1
|
|
child
|
|
end
|
|
|
|
# Adds a child
|
|
def add(child)
|
|
position = @children.size - @last_items_count
|
|
add_at(child, position)
|
|
end
|
|
alias :<< :add
|
|
|
|
# Removes a child
|
|
def remove!(child)
|
|
@children.delete(child)
|
|
@last_items_count -= +1 if child && child.last
|
|
child.parent = nil
|
|
child
|
|
end
|
|
|
|
# Returns the position for this node in it's parent
|
|
def position
|
|
self.parent.children.index(self)
|
|
end
|
|
|
|
# Returns the root for this node
|
|
def root
|
|
root = self
|
|
root = root.parent while root.parent
|
|
root
|
|
end
|
|
end
|
|
end
|