class Locomotive::Steam::Liquid::Tags::Nav
Display the children pages of the site, current page or the parent page. If not precised, nav is applied on the current page. The html output is based on the ul/li tags.
Usage:
{% nav site %} => <ul class=“nav”><li class=“on”><a href=“/features”>Features</a></li></ul>
{% nav site, no_wrapper: true, exclude: 'contact|about', id: 'main-nav', class: 'nav', active_class: 'on' }
Constants
- Syntax
Attributes
Public Class Methods
# File lib/locomotive/steam/liquid/tags/nav.rb, line 21 def initialize(tag_name, markup, options) markup =~ Syntax @source = ($1 || 'page').gsub(/"|'/, '') self.set_options(markup, options) super end
Public Instance Methods
# File lib/locomotive/steam/liquid/tags/nav.rb, line 31 def render(context) self.set_vars_from_context(context) set_template_if_asked # get all the children of a source: site (index page), parent or page. pages = children_of(fetch_starting_page) _output = self.build_entries_output(pages, context) if self.no_wrapper? _output else self.render_tag(:nav, id: @_options[:id], css: @_options[:class]) do self.render_tag(:ul) { _output } end end end
Protected Instance Methods
# File lib/locomotive/steam/liquid/tags/nav.rb, line 291 def bootstrap? @_options[:bootstrap].to_bool end
Build recursively the links of all the pages.
@param [ Array ] pages List of pages
@return [ String ] The final HTML output
# File lib/locomotive/steam/liquid/tags/nav.rb, line 57 def build_entries_output(pages, depth = 1, context) output = [] pages.each_with_index do |page, index| css = [] css << 'first' if index == 0 css << 'last' if index == pages.size - 1 output << self.render_entry_link(page, css.join(' '), depth, context) end output.join("\n") end
Get all the children of page. It filters the collection to only return pages which will be displayed in the nav.
# File lib/locomotive/steam/liquid/tags/nav.rb, line 86 def children_of(page) children = (page_repository.children_of(page) || []) children .map { |child| decorate_page(child) } .select { |child| self.include_page?(child) } end
# File lib/locomotive/steam/liquid/tags/nav.rb, line 286 def decorate_page(page) klass = Locomotive::Steam::Decorators::I18nDecorator klass.new(page, current_locale, current_site.default_locale) end
Return the css of an entry (page).
@param [ Object ] page The page @param [ String ] extra_css The extra css
@return [ String ] The css
# File lib/locomotive/steam/liquid/tags/nav.rb, line 168 def entry_css(page, extra_css = '') ['link'].tap do |css| css << @_options[:active_class] if self.page_selected?(page) css << extra_css if !extra_css.blank? end.join ' ' end
Return the label of an entry. It may use or not the template given by the snippet option.
@param [ Object ] page The page
@return [ String ] The label in HTML
# File lib/locomotive/steam/liquid/tags/nav.rb, line 138 def entry_label(page, context) icon = @_options[:icon] ? '<span></span>' : '' title = @_options[:liquid_render] ? @_options[:liquid_render].render({ 'page' => page }, registers: context.registers) : page.title if icon.blank? title elsif @_options[:icon] == 'after' "#{title} #{icon}" else "#{icon} #{title}" end end
Return the localized url of an entry (page).
@param [ Object ] page The page
@return [ String ] The localized url
# File lib/locomotive/steam/liquid/tags/nav.rb, line 157 def entry_url(page) services.url_builder.url_for(page) end
Get the first page used to list all the children. It depends on the source: site, parent, page or a fullpath
# File lib/locomotive/steam/liquid/tags/nav.rb, line 74 def fetch_starting_page case @source when 'site' then page_repository.root when 'parent' then page_repository.parent_of(current_page) || current_page when 'page' then current_page else page_repository.by_fullpath(@source) end end
Determine whether or not a page should be a part of the menu.
@param [ Object ] page The page
@return [ Boolean ] True if the page can be included or not
# File lib/locomotive/steam/liquid/tags/nav.rb, line 99 def include_page?(page) if !page.listed? || page.templatized? || !page.published? false elsif @_options[:exclude] (page.fullpath =~ @_options[:exclude]).nil? else true end end
# File lib/locomotive/steam/liquid/tags/nav.rb, line 295 def no_wrapper? @_options[:no_wrapper].to_bool end
Determine wether or not a page is currently the displayed one.
@param [ Object ] page The page
@return [ Boolean ]
# File lib/locomotive/steam/liquid/tags/nav.rb, line 115 def page_selected?(page) self.current_page.fullpath =~ /^#{page.fullpath}(\/.*)?$/ end
Parse the template of the snippet give in option of the tag. If the template_name contains a liquid tag or drop, it will be used an inline template.
# File lib/locomotive/steam/liquid/tags/nav.rb, line 254 def parse_snippet_template(template_name) source = if template_name.include?('{{') template_name else snippet = services.snippet_finder.find(template_name) if snippet snippet.liquid_source else Locomotive::Common::Logger.warn "[Liquid][Nav] unable to find the #{template_name} snippet" nil end end source ? ::Liquid::Template.parse(source) : nil end
Determine if the children of a page have to be rendered or not. It depends on the depth passed in the option.
@param [ Object ] page The page @param [ Integer ] depth The current depth
@return [ Boolean ] True if the children have to be rendered.
# File lib/locomotive/steam/liquid/tags/nav.rb, line 127 def render_children_for_page?(page, depth) depth.succ <= @_options[:depth].to_i && children_of(page).any? end
Recursively create a nested unordered list for the depth specified.
@param [ Array ] entries The children of the page @param [ Integer ] depth The current depth
@return [ String ] The HTML code
# File lib/locomotive/steam/liquid/tags/nav.rb, line 209 def render_entry_children(page, depth, context) entries = children_of(page) css = self.bootstrap? ? 'dropdown-menu' : '' unless entries.empty? self.render_tag(:ul, id: "#{@_options[:id]}-#{page.slug.to_s.dasherize}", css: css) do self.build_entries_output(entries, depth, context) end else '' end end
Return the HTML output of a page and its children if requested.
@param [ Object ] page The page @param [ String ] css The current css to apply to the entry @param [ Integer] depth Used to know if the children has to be added or not.
@return [ String ] The HTML output
# File lib/locomotive/steam/liquid/tags/nav.rb, line 183 def render_entry_link(page, css, depth, context) url = self.entry_url(page) label = self.entry_label(page, context) css = self.entry_css(page, css) options = '' if self.render_children_for_page?(page, depth) && self.bootstrap? url = '#' label += %{ <b class="caret"></b>} css += ' dropdown' options = %{ class="dropdown-toggle" data-toggle="dropdown"} end self.render_tag(:li, id: "#{page.slug.to_s.dasherize}-link", css: css) do children_output = depth.succ <= @_options[:depth].to_i ? self.render_entry_children(page, depth.succ, context) : '' %{<a href="#{url}"#{options}>#{label}</a>} + children_output end end
Render any kind HTML tags. The content of the tag comes from the block.
@param [ String ] tag_name Name of the HTML tag (li, ul, div, …etc). @param [ String ] html_options Id, class, ..etc
@return [ String ] The HTML
# File lib/locomotive/steam/liquid/tags/nav.rb, line 278 def render_tag(tag_name, html_options = {}, &block) options = [''] options << %{id="#{html_options[:id]}"} if html_options[:id].present? options << %{class="#{html_options[:css]}"} if html_options[:css].present? %{<#{tag_name}#{options.join(' ')}>#{yield}</#{tag_name}>} end
Set the value (default or assigned by the tag) of the options.
# File lib/locomotive/steam/liquid/tags/nav.rb, line 224 def set_options(markup, options) @_options = { id: 'nav', class: '', active_class: 'on', bootstrap: false, no_wrapper: false } markup.scan(::Liquid::TagAttributes) { |key, value| @_options[key.to_sym] = value.gsub(/"|'/, '') } @_options[:exclude] = Regexp.new(@_options[:exclude]) if @_options[:exclude] end
# File lib/locomotive/steam/liquid/tags/nav.rb, line 232 def set_template_if_asked if @_options[:snippet] if template = parse_snippet_template(@_options[:snippet]) @_options[:liquid_render] = template end end end
Avoid to call context.registers to get the current page.
# File lib/locomotive/steam/liquid/tags/nav.rb, line 242 def set_vars_from_context(context) self.current_site = context.registers[:site] self.current_page = context.registers[:page] self.services = context.registers[:services] self.current_locale = context.registers[:locale] self.page_repository = services.repositories.page end