Splitting the navigation

Every site has navigation: top menus, side menus (do they still exist?), bread crumbs, sitemaps, etc. The common approach in a Tridion implementation is to derive the navigation from the structure groups.

This is commonly done as follows:

  • Create a Navigation page template in Tridion which traverses the entire structure
  • Leave out some structure groups because you don’t really want them in the navigation
  • Write out this information as XML
  • Consume the XML from the web pages to show the navigation items

 

To change the navigation, all the editors have to do is add/change/delete a structure group and republish the Navigation system page (which uses the Navigation page template).

If the web site runs .NET, chances are the navigation will be published in the form of a SiteMap. For this article I will assume this is the case, but the same principles apply when you’re working with Java.

 

Help, my page is live!

This is how it has been done for years, and by and large it works fine. Performance is good, it is easy to understand and easy to manage, and best of all: it is a low-tech solution which works (in slight variations) on every target platform (java, .NET, even ASP).

Still, I do hear complaints about this solution every once in a while. They usually come from organizations with a big web site, with lots of changes to the navigation structure, and many different editors working to maintain it all. The complaint goes like this:

I am working on a new section of the site which is not yet ready to be published, and a colleague goes and publishes the navigation, making my own new section visible before its time!

This is – of course – an understandable and reasonable complaint. My job is to help Tridion users, so I thought of a solution. I wanted to keep the advantages of the ‘navigation xml’ approach, but tweak it just a little bit to avoid problems like the one quoted above.

The problem lies not in the ‘xml approach’ per se, but rather in the fact that there is only one XML page which carries the information about navigational structure from the CMS to the web site.

Normally (at least in the organizations I work for), the editors (or Content Managers, or whatever they call themselves) will divide the work along the lines of sections of the site:

  • Products versus services
  • Business versus consumers
  • Sales versus support
  • etc.

If we could just split up this information into chunks, we would have a solution! One chunk for ‘products’, managed by the people who are responsible for products, another one for ‘services’, managed by the services crowd.

From a technical angle I would prefer to minimize the changes to the solution. So: split up the navigation page at the last possible moment, and paste the chunks  back together againat the earliest possible moment. In a picture, that would look like this:

splitting up navigation

To achieve this, we need to make two changes:

  • Change the template so that it stops iterating over the structure if a ‘subnavigation’ page is found, and add a link to the subnavigation to the main navigation structure
  • Change the SiteMapProvider which reads the SiteMap information from your navigation page, so that it follows the links to the ‘subnavigation’ pages and merges them into one big SiteMap

The main SiteMap when generated by the template would look something like this:

<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0"> 
  <siteMapNode id="tcm:6-247-64" url="/business" title="Business">
    <siteMapNode id="tcm:6-246-64" url="/business/service1.html" 
      title="An interesting service" />
    <siteMapNode id="tcm:6-147-64" url="/business/service2.html" 
      title="Some other service" />
  </siteMapNode>
  <siteMapNode id="tcm:6-301-64" url="/consumer" title="Consumer" 
    subnavigation="/consumer/navigation.xml">
</siteMap>

As you can see, we have two structure groups on the top level: business and consumer. The consumer branch does not contain any pages, but it does specify a subnavigation url: /consumer/navigation.xml.

This consumer navigation looks like this:

<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0"> 
  <siteMapNode id="tcm:6-301-64" url="/consumer" title="Consumer">
    <siteMapNode id="tcm:6-346-64" url="consumer/product1.html" 
      title="An interesting product" />
    <siteMapNode id="tcm:6-347-64" url="/consumer/product2.html" 
      title="Some other product" />
  </siteMapNode>
</siteMap>

When the navigation is requested in the web application, however, a class called DistributedSitemapProvider makes sure that the whole structure is merged again, and the XML looks like this:

<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0"> 
  <siteMapNode id="tcm:6-247-64" url="/business" title="Business">
    <siteMapNode id="tcm:6-246-64" url="/business/service1.html" 
      title="An interesting service" />
    <siteMapNode id="tcm:6-147-64" url="/business/service2.html" 
      title="Some other service" />
  </siteMapNode>
 <siteMapNode id="tcm:6-301-64" url="/consumer" title="Consumer">    
   <siteMapNode id="tcm:6-346-64" url="consumer/product1.html"         
     title="An interesting product" />
   <siteMapNode id="tcm:6-347-64" url="/consumer/product2.
     title="Some other product" />
  </siteMapNode>
</siteMap>

 

As you can see, the subnavigation replaces the node in the main navigation. The end result is a completely standard sitemap which you can use normally.

The mechanism is iterative: you can have subnavigations on any level, and you can nest one subnav inside another as well.

 

Download

Download source code: Distributed Sitemap

The template class should be built and uploaded to Tridion. It creates a TBB called Distributed Sitemap which should be included in a page template.

The web app code should be included in your web application and should run on any ASP.NET site.