Building dynamic navs

Okay, so I’m trying my hand at building a dynamic nav within Radiant
for the first time. The top nav is static and I used the navigation
tag for it. Though when someone clicks on one of the top links
potentially it could display sub links beneath it such as this when
the user has clicked the about us page:

About Us

  • Faculty
  • History
  • Jobs
  • Policies
    Admissions
    Calendar
    Contact Us
    Education

The problem is when I click on About Us all the sub links have the
about us page properties. I’ve tried several things with no better
results. My main approach has been to create a sub_nav page part in
my top level pages that I have the navigation tag use if selected.
Here’s the navigation tag:

<r:navigation urls=“About Us: /about_us/; Admissions: /admissions/;
Calendar: /calendar/; Contact Us: /contact_us/; Education:
/education/”>
<r:normal>

  • <r:title />
  • </r:normal>
    <r:here>
  • <r:title />
  • <r:if_content
    part=“subnav”>
    <r:content part=“subnav” /></r:if_content></r:here>
    </r:navigation>

    For the sub_nav page part I’ve tried a few different things such as:

    <r:children:each>

  • I noticed some comments on using the r:child in some cases so I tried
    that:

    <r:children:each><r:child>

  • Then I figured maybe I needed to explicitly find the about_us page such
    as this:

    <r:find url="/about_us">
    <r:children:each><r:child>

  • So did I miss something basic or am I going down the wrong hole here?
    Thanks for the help.

    Cheers,
    Marty

    Marty,

    The problem is that inside the <r:navigation> tag, the url and
    title properties don’t belong to an actual page, but are the
    information that you put in the urls attribute of the tag. So you
    could create a navigation link to a non-existent page, hypothetically.
    Perhaps you need something that traverses the children of the top
    page, then conditionally their children.

    Sean

    I wrote my own tag (wrapped in an extension) to do this Marty.

    I’ll paste the code snips in here they may be able to help you out, if
    you want more I could post a zip file somewhere.

    Dynamically generates collection of links.

    Very similar to ‘navigation’ w/some differences.

    Pulls all children and adds parent first.

    tag ‘dynamic_secondary_navigation’ do |tag|
    hash = tag.locals.dynamic_secondary_navigation = {}
    tag.expand
    raise TagError.new(“dynamic_secondary_navigation' tag must include anormal’ tag”) unless hash.has_key? :normal
    result = []

       fp = FantasticPage.new(tag.locals.page)
       p = fp.top_level_page
       pairs = Array.new
       pairs << ['Overview', p.url]
       for child in p.children
         pairs << [child.title, child.url]
       end
    
       pairs.each do |title, url|
         compare_url = remove_trailing_slash(url)
         page_url = remove_trailing_slash(self.url)
         hash[:title] = title
         hash[:url] = url
         case page_url
         when compare_url
           result << (hash[:here] || hash[:selected] || 
    

    hash[:normal]).call
    else
    result << hash[:normal].call
    end
    end
    between = hash.has_key?(:between) ? hash[:between].call : ’ ’
    result.join(between)
    end


    Class that the tag above calls:

    class FantasticPage

    attr_accessor :page

    Set the page.

    def initialize(page)
    @page = page
    end

    Returns ‘top_level_page’ one down from root.

    NOTE: Only works for 2nd and 3rd level pages.

    def top_level_page
    url = @page.url
    pieces = @page.url.split("/")
    if pieces.size == 3
    url = @page.parent.url
    end
    return Page.find_by_url(url)
    end

    end

    On 2/8/07, Michael J. [email protected] wrote:

    I wrote my own tag (wrapped in an extension) to do this Marty.

    I’ll paste the code snips in here they may be able to help you out, if
    you want more I could post a zip file somewhere.

    Yeah, I think this is probably the road I need to go down. However, I
    have to wonder, aren’t more radiant sites needing something like this?
    I suppose you could do if_url matches but it would seem smarter and
    simpler if you could just dynamically make nav off your existing pages
    especially if you want to have a selected page’s sub nav to fit into
    the main nav bar.

    Michael, I would like to see more. Though I haven’t dived into any of
    the radius code yet I would have to wonder if you take all the
    children of a page, is there a simple way to filter out certain pages
    such as by page type? For instance, I might not want certain pages to
    be in the main nav such as contact us but would still want them off
    the root that might be linked in the footer, for example. Another
    example would be the css files off the root.

    Does anyone else have a similar solution such as Michael’s out there?

    Cheers,
    Marty

    Does anyone else have a similar solution such as Michael’s out there?

    Here’s an example to build dynamic tree navigation:

    http://pastie.caboo.se/39956

    It produces:

    http://pastie.caboo.se/39959

    Hopefully, this inspires some ideas for you.

    Layout/formatting is controlled in css.

    BTW- Thanks Michael! for your post. It helped me while I worked on this
    tree
    navigation tag.

    Todd

    PS- I don’t like the hardcoding for ul, li, and css classes. It
    wouldn’t be
    that difficult to extract refactor the hardcode into configurable tag
    attributes/nodes.

    PS 2, Electric Boogaloo- I don’t understand while I had to call
    options.dup, but
    if I didn’t the value was being concatenated each time through the
    getBranch
    call.

    I wanted to post a follow-up on my original email on building dynamic
    navs. Thanks to the several folks who have posted their own
    solutions. I chatted a couple times with Sean and came up with an
    almost all snippet/tag solution. The only trick is I need this new
    tag based on a recent patch by Sean that exposes the
    tag.globals.actual_page. Here’s the tag:

    tag “if_ancestor_or_self” do |tag|
    tag.expand if (tag.globals.actual_page.ancestors +
    [tag.globals.actual_page]).include?(tag.locals.page)
    end

    So this guy essentially will expand his contents if the current page
    matches the comparing page or one of its parents.

    Here is the snippet code that I use to build my left nav:

    And the sub-nav snippet looks like this:
    <r:unless_content part=“no-map”>

  • What all this builds is a nested unordered list of links found off the
    root page. I filter out pages that I don’t want by putting a no-map
    page part on them. This also plays nicely with Sean’s original
    sitemap snippet. This pretty much meets my needs but it may also be
    better expressed as its own tag. For one the html output has tons of
    extra space as well as an empty

      for the lowest level children.

      Cheers,
      Marty

    to add my 2 cents to this conversation…

    Uses all standart procedures besides the “parent” tag, which can be
    added as shown here >
    http://dev.radiantcms.org/radiant/wiki/HowToDefineGlobalTags

    it basically uses the r:navigation tag, in conjunction with the r:parent
    and r:children tag…to get all data needed

    obviously you need to patch up the css if you want a vertical menu like
    in my case

    #navigation ul, ul {margin:0px; padding:0px; list-style: none;}
    #navigation ul li {margin:0px; padding:0px; list-style: none; }

    maybe this helps someone out
    best
    Flo,