How to Create Stateful Navigation in Radiant CMS

In the past, I haven’t blogged very much about Radiant CMS – the content management system I created. Part of that is due to the fact that a lot of my early documentation efforts were focused on writing information that would appear on RadiantCMS.org itself, either in blog posts or on the project wiki. Part of it is due to feeling self-conscious (for whatever reason) about blogging about my own project. Another part of it, perhaps the largest part, is due to the fact that I haven’t done a very good job of blogging consistently about anything.

But no more. This year I am working hard to turn over a new leaf, and blogging consistently is my #1 priority. For content I’m going to be pulling from a number of projects I’ve worked on in the past, and Radiant will be featured prominently.

For starters I’d like to kick off this series with a discussion of how to create stateful navigation in Radiant CMS. When I say stateful navigation I mean navigation that indicates where you are on a web site. For instance, in the header of my web site you can see the following links:

“Portfolio” is a lighter color and is set in bold type instead of normal type like the other two links. This indicates to the user where they are on my site. If they were viewing my weblog, “Weblog” would appear bold and the other two links as normal text, and so forth.

Approach #1 – If and Unless

To achieve this effect, I have resorted to a couple of Radius tags. Radiant comes packaged with a powerful macro-like language called Radius that is used to transform snippets of HTML into a working web page. The format is relatively simple. It looks a lot like XML or HTML, except that all of the tags begin with the r: prefix.

On my site, I have three links and I’m using a bit of a brute force technique to get it to work for me. This is taken straight from the main layout of my site:

<div id="navigation">
  <ul>
    <r:if_url matches="^/portfolio"><li class="here"><a href="/portfolio/">Portfolio</a></li></r:if_url>
    <r:unless_url matches="^/portfolio"><li><a href="/portfolio/">Portfolio</a></li></r: unless_url>
    <r:if_url matches="^/(weblog|articles)"><li class="here"><a href="/weblog/">Weblog</a></li></r:if_url>
    <r:unless_url matches="^/(weblog|articles)"><li><a href="/weblog/">Weblog</a></li></r:unless_url>
    <r:if_url matches="^/about"><li class="here"><a href="/about/">About</a></li></r:if_url>
    <r:unless_url matches="^/about"><li><a href="/about/">About</a></li></r:unless_url>
  </ul>
</div>

As you can see, I’m making heavy use of the <r:if_url /> and <r:unless_url /> tags. These tags both use the matches attribute, which matches the URL against a regular expression. (There is a great introduction to regular expressions in the free version of Programming Ruby, here). The <r:if_url /> tag will only output its contents if the URL matches the given regular expression (and the reverse is true for <r:unless_url />).

The downside of this technique is that it is extremely verbose. For each link I have to create a set of <r:if_url /> and <r:unless_url /> tags that contain the state of the link when it is selected and when it is not. The advantage of this technique is that it allows me to use regular expressions to match a huge variety of URLs. This works out well, especially for the “Weblog” link, which should show itself as selected when the URL starts with either “/weblog” or “/articles”.

Approach #2 – The Navigation Tag

If I hadn’t needed to use fancy regular expressions to build my navigation correctly I could have used another set of tags that would construct the navigation more efficiently. The <r:navigation /> tag is designed specifically for rendering this kind of navigation:

<div id="navigation">
  <ul>
    <r:navigation urls="Portfolio: /portfolio/ | Weblog: /weblog/ | About: /about/">
      <r:here><li class="here"><a href="<r:url />"><r:title /></a></li></r:here>
      <r:selected><li class="here"><a href="<r:url />"><r:title /></a></li></r:selected>
      <r:normal><li><a href="<r:url />"><r:title /></a></li></r:normal>
    </r:navigation>
  </ul>
</div>

The <r:navigation /> tag has one attribute, urls. This attribute contains multiple key/value pairs of the title/URL of each link in the navigation. Inside of the <r:navigation /> tags are three additional tag sets containing the HTML for the three different link states. here is the state of a link when the URL matches exactly. selected is the state of a link when the user is on a child page of the given URL. And normal is the state of a link under normal circumstances.

Approach #3 – Clever Use of the Page Slug

There is one final approach that is sometimes useful when dealing with stateful navigation. Ryan Heneise first talked about this approach in an article on ArtOfMission.com. Unfortunately, that article is no longer available so I’ll outline the general technique here.

For starters, this approach makes clever use of CSS and the page slug. The page slug is the last part of the URL. It generally follows the page title, but it is lowercase and it replaces all spaces and punctuation with dashes. So for the root level page “About Us” the slug is generally “about-us”. I say “generally” because the end user can customize the page slug to be whatever they want.

What Ryan realized was that he could use the current page’s slug to set the body class in his main layout:

<body class="<r:slug />">

He could then use a couple of CSS rules to achieve the same effect:

body.portfolio li#portfolio,
body.weblog li#weblog,
body.about li#about
{
  color: white;
  font-weight: bold;
}

Conclusion

So there you have it: three fantastic ways to achieve stateful navigation with Radiant CMS. Hopefully I’ve primed the pump a little and your head is already spinning with ways to do cool things with Radiant.

What are you doing with Radiant CMS?