# Building dynamic navs

**URL:** <https://www.ruby-forum.com/t/building-dynamic-navs/84859>\
**Category:** Radiant CMS\
**Created:** [February 8, 2007, 5:50am UTC](https://www.ruby-forum.com/t/building-dynamic-navs/84859 "2007-02-08T05:50:22Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![djmorphine](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/f0a364/32.png) [@djmorphine](https://www.ruby-forum.com/u/djmorphine)\
**Post date:** [February 8, 2007, 5:50am UTC](https://www.ruby-forum.com/t/building-dynamic-navs/84859/1 "2007-02-08T05:50:22Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![djmorphine](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/f0a364/32.png) [@djmorphine](https://www.ruby-forum.com/u/djmorphine)\
**Post date:** [February 8, 2007, 2:58pm UTC](https://www.ruby-forum.com/t/building-dynamic-navs/84859/2 "2007-02-08T14:58:20Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![djmorphine](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/f0a364/32.png) [@djmorphine](https://www.ruby-forum.com/u/djmorphine)\
**Post date:** [February 8, 2007, 6:21pm UTC](https://www.ruby-forum.com/t/building-dynamic-navs/84859/3 "2007-02-08T18:21:45Z")

</div>

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 a`normal’ 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

---

<div class="post-metadata">

**Author:** ![djmorphine](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/f0a364/32.png) [@djmorphine](https://www.ruby-forum.com/u/djmorphine)\
**Post date:** [February 13, 2007, 5:47am UTC](https://www.ruby-forum.com/t/building-dynamic-navs/84859/4 "2007-02-13T05:47:07Z")

</div>

On 2/8/07, Michael J. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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

---

<div class="post-metadata">

**Author:** ![djmorphine](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/f0a364/32.png) [@djmorphine](https://www.ruby-forum.com/u/djmorphine)\
**Post date:** [February 13, 2007, 12:50pm UTC](https://www.ruby-forum.com/t/building-dynamic-navs/84859/5 "2007-02-13T12:50:48Z")

</div>

> 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](http://pastie.caboo.se/39956)

It produces:

[http://pastie.caboo.se/39959](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.

---

<div class="post-metadata">

**Author:** ![djmorphine](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/f0a364/32.png) [@djmorphine](https://www.ruby-forum.com/u/djmorphine)\
**Post date:** [March 1, 2007, 6:48am UTC](https://www.ruby-forum.com/t/building-dynamic-navs/84859/6 "2007-03-01T06:48:17Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![djmorphine](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/f0a364/32.png) [@djmorphine](https://www.ruby-forum.com/u/djmorphine)\
**Post date:** [February 22, 2007, 12:26am UTC](https://www.ruby-forum.com/t/building-dynamic-navs/84859/7 "2007-02-22T00:26:26Z")

</div>

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](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,
