2010-07-06 00:05:47 +00:00
|
|
|
module Locomotive
|
2010-07-23 20:09:54 +00:00
|
|
|
module Liquid
|
|
|
|
module Tags
|
2011-01-02 22:58:06 +00:00
|
|
|
# Display the children pages of the site, current page or the parent page. If not precised, nav is applied on the current page.
|
2010-07-06 00:05:47 +00:00
|
|
|
# The html output is based on the ul/li tags.
|
|
|
|
#
|
2011-01-24 09:00:02 +00:00
|
|
|
# Passing through depth will control how many nested children are output
|
|
|
|
#
|
2010-07-06 00:05:47 +00:00
|
|
|
# Usage:
|
|
|
|
#
|
|
|
|
# {% nav site %} => <ul class="nav"><li class="on"><a href="/features">Features</a></li></ul>
|
|
|
|
#
|
2011-01-24 09:00:02 +00:00
|
|
|
# {% nav site, no_wrapper: true, depth: 1, exclude: 'contact|about', id: 'main-nav' }
|
2011-01-02 22:58:06 +00:00
|
|
|
#
|
2010-07-06 00:05:47 +00:00
|
|
|
class Nav < ::Liquid::Tag
|
2010-07-23 20:09:54 +00:00
|
|
|
|
2010-07-06 00:05:47 +00:00
|
|
|
Syntax = /(#{::Liquid::Expression}+)?/
|
2010-07-23 20:09:54 +00:00
|
|
|
|
2010-08-20 00:31:01 +00:00
|
|
|
def initialize(tag_name, markup, tokens, context)
|
2010-07-06 00:05:47 +00:00
|
|
|
if markup =~ Syntax
|
2011-01-02 22:58:06 +00:00
|
|
|
@source = ($1 || 'page').gsub(/"|'/, '')
|
2011-01-24 09:00:02 +00:00
|
|
|
@options = { :id => 'nav', :depth => 1 }
|
2011-01-03 10:50:09 +00:00
|
|
|
markup.scan(::Liquid::TagAttributes) { |key, value| @options[key.to_sym] = value.gsub(/"|'/, '') }
|
2011-01-24 09:00:02 +00:00
|
|
|
|
2011-01-03 10:50:09 +00:00
|
|
|
@options[:exclude] = Regexp.new(@options[:exclude]) if @options[:exclude]
|
2010-07-06 00:05:47 +00:00
|
|
|
else
|
2010-07-13 00:46:17 +00:00
|
|
|
raise ::Liquid::SyntaxError.new("Syntax Error in 'nav' - Valid syntax: nav <page|site> <options>")
|
2010-07-06 00:05:47 +00:00
|
|
|
end
|
2010-07-23 20:09:54 +00:00
|
|
|
|
2010-07-06 00:05:47 +00:00
|
|
|
super
|
|
|
|
end
|
2010-07-23 20:09:54 +00:00
|
|
|
|
2010-07-06 00:05:47 +00:00
|
|
|
def render(context)
|
2011-01-03 10:50:09 +00:00
|
|
|
children_output = []
|
2010-07-23 20:09:54 +00:00
|
|
|
|
2011-01-03 10:50:09 +00:00
|
|
|
entries = fetch_entries(context)
|
2011-01-02 22:58:06 +00:00
|
|
|
|
2011-01-03 10:50:09 +00:00
|
|
|
entries.each_with_index do |p, index|
|
|
|
|
css = []
|
|
|
|
css << 'first' if index == 0
|
|
|
|
css << 'last' if index == entries.size - 1
|
2011-01-02 22:58:06 +00:00
|
|
|
|
2011-01-24 09:00:02 +00:00
|
|
|
children_output << render_entry_link(p,css.join(' '),1)
|
2010-07-06 00:05:47 +00:00
|
|
|
end
|
|
|
|
|
2011-01-02 22:58:06 +00:00
|
|
|
output = children_output.join("\n")
|
2010-10-30 22:30:30 +00:00
|
|
|
|
2011-01-03 10:50:09 +00:00
|
|
|
if @options[:no_wrapper] != 'true'
|
|
|
|
output = %{<ul id="#{@options[:id]}">\n#{output}</ul>}
|
|
|
|
end
|
2010-10-30 22:30:30 +00:00
|
|
|
|
2010-07-06 00:05:47 +00:00
|
|
|
output
|
|
|
|
end
|
2010-07-23 20:09:54 +00:00
|
|
|
|
2010-07-06 00:05:47 +00:00
|
|
|
private
|
2011-01-24 23:48:59 +00:00
|
|
|
|
|
|
|
# Determines root node for the list
|
2011-01-03 10:50:09 +00:00
|
|
|
def fetch_entries(context)
|
|
|
|
@current_page = context.registers[:page]
|
|
|
|
|
|
|
|
children = (case @source
|
|
|
|
when 'site' then context.registers[:site].pages.index.minimal_attributes.first # start from home page
|
|
|
|
when 'parent' then @current_page.parent || @current_page
|
|
|
|
when 'page' then @current_page
|
|
|
|
else
|
|
|
|
context.registers[:site].pages.fullpath(@source).minimal_attributes.first
|
|
|
|
end).children_with_minimal_attributes.to_a
|
|
|
|
|
|
|
|
children.delete_if { |p| !include_page?(p) }
|
|
|
|
end
|
|
|
|
|
2011-01-24 23:48:59 +00:00
|
|
|
# Returns a list element, a link to the page and its children
|
2011-01-24 09:00:02 +00:00
|
|
|
def render_entry_link(page,css,depth)
|
2011-01-02 22:58:06 +00:00
|
|
|
selected = @current_page.fullpath =~ /^#{page.fullpath}/ ? ' on' : ''
|
2010-07-23 20:09:54 +00:00
|
|
|
|
2010-07-13 00:46:17 +00:00
|
|
|
icon = @options[:icon] ? '<span></span>' : ''
|
|
|
|
label = %{#{icon if @options[:icon] != 'after' }#{page.title}#{icon if @options[:icon] == 'after' }}
|
2010-07-23 20:09:54 +00:00
|
|
|
|
2011-01-24 09:00:02 +00:00
|
|
|
output = %{<li id="#{page.slug.dasherize}" class="link#{selected} #{css}">}
|
|
|
|
output << %{<a href="/#{page.fullpath}">#{label}</a>}
|
|
|
|
output << render_entry_children(page,depth.succ) if (depth.succ <= @options[:depth].to_i)
|
|
|
|
output << %{</li>}
|
|
|
|
|
|
|
|
output.strip
|
|
|
|
end
|
|
|
|
|
2011-01-24 23:48:59 +00:00
|
|
|
# Recursively creates a nested unordered list for the depth specified
|
2011-01-24 09:00:02 +00:00
|
|
|
def render_entry_children(page,depth)
|
|
|
|
output = %{}
|
|
|
|
|
2011-01-24 23:48:59 +00:00
|
|
|
children = page.children_with_minimal_attributes.reject { |c| !include_page?(c) }
|
2011-01-24 09:00:02 +00:00
|
|
|
if children.present?
|
|
|
|
output = %{<ul id="#{@options[:id]}-#{page.slug.dasherize}">}
|
|
|
|
children.each do |c, page|
|
|
|
|
css = []
|
|
|
|
css << 'first' if children.first == c
|
|
|
|
css << 'last' if children.last == c
|
|
|
|
|
|
|
|
output << render_entry_link(c,css.join(' '),depth)
|
|
|
|
end
|
|
|
|
output << %{</ul>}
|
|
|
|
end
|
|
|
|
|
|
|
|
output
|
2010-07-06 00:05:47 +00:00
|
|
|
end
|
2011-01-24 23:48:59 +00:00
|
|
|
|
|
|
|
# Determines whether or not a page should be a part of the menu
|
|
|
|
def include_page?(page)
|
|
|
|
if page.templatized? || !page.published?
|
|
|
|
false
|
|
|
|
elsif @options[:exclude]
|
|
|
|
(page.fullpath =~ @options[:exclude]).nil?
|
|
|
|
else
|
|
|
|
true
|
|
|
|
end
|
|
|
|
end
|
2010-07-23 20:09:54 +00:00
|
|
|
|
2010-07-06 00:05:47 +00:00
|
|
|
::Liquid::Template.register_tag('nav', Nav)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2010-07-23 20:09:54 +00:00
|
|
|
end
|