Textpattern tips, tutorials and code snippets

Assign active class for two or more sections to a single navigation item

The section_list is a very versatile tag for building section-based navigation. It includes attributes that define the markup, such as wraptag and break, as well as simple API hooks to select and order the sections you want to include (or exclude) in your navigation. It even has a syntax for giving the section you are currently browsing an active class in the menu.

For a simple navigation menu that lists the sections you specify and gives the current section an active class, something like this may be all you need:

<txp:section_list
	active_class="active"
	break="li"
	default_title="Home"
	include_default="1"
	sections="about,articles,news,etc,etc,etc"
	wraptag="ul"/>

The section_list tag will pull the titles defined in your sections tab and pour them into an unordered list, linking each section title to the landing page of its section. To give you a styling hook for the current section-link, it adds a class attribute to the anchor tag of the section you are currently viewing1:

<ul>
	<li><a href="http://site.url/">Home</a></li>
	<li><a class="active" href="http://site.url/about/">About</a></li>
	<li><a href="http://site.url/articles/">Archive</a></li>
	<li><a href="http://site.url/news/">Presswire</a></li>
	<!-- Et cetera... -->
</ul>

But sometimes you have a site that needs more nuanced navigation. You might have a site map that includes several sub-sections under a single navigation item. Without worrying about modifying Textpattern to accomodate a Byzantine section hierarchy, you can still use the section_list tag to make your main section “active” even when you are browsing one of it’s “sub-sections”.

Contain or be contained

The key is that section_list is one of the many Textpattern tags that can be used singly as above, or as a container. In order to assign an “active” class to an item when viewing its “sub-sections”, you need to use it as a container or give it a form attribute with a corresponding form for its contents.

Here’s an example of the same section list used as a container tag:

<txp:section_list
	active_class="active"
	break="li"
	default_title="Home"
	include_default="1"
	sections="about,articles,news,etc,etc,etc"
	wraptag="ul"><txp:section link="1" title="1"/></txp:section_list>

Handling the section_list as a container can be tricky: Textpattern no longer issues an “active” class for the item you’re currently browsing; since you’ve given the tag contents the section link tag overrides the section_list’s active_class attribute. The class will have to be hard-coded into the contained tags and markup.

Trickier still teasing out this section that you are browsing from this section in the list, and setting up a conditional statement that allows you to render the “active” class when you need it.

Let’s put this together step-by-step

First, you need a section title, linked to the corresponding section:

<a href="<txp:site_url/><txp:section/>/"><txp:section title="1"/></a>

Both of the above section tags refer to the current section_list item, not the current section being browsed. This is important, because in most contexts, Textpattern will parse this tag and output the section you are viewing in the browser.

Wait— this form also has to link to the site’s homepage, and we don’t want anything pointing to http://site.url/default/. So we’ll need to modify the markup a little. If you think this is a job for Textpattern’s if_section tag— well, so did I. But unlike section, Textpattern evaluates if_section based on the current browsing section. This calls for a variable2:

<txp:variable name="this-section_list-item">
	<txp:section/>
</txp:variable>
<a
	href="<txp:site_url/><txp:if_variable name="this-section_list-item" value="default"><txp:else/><txp:section/>/</txp:if_variable>">
		<txp:section title="1"/>
</a>

Ah, much better. What we’ve done here is create a variable called this-section_list-item, so that we can check which section is being listed in this instance using if_variable. If this-section_list-item is “default”, Textpattern knows that we are linking to the homepage, and we shouldn’t append a section name to the URL.

But we still don’t have any “active” class action. To define a class attribute for the current browsing section, @if_section@ finally comes into play:

<a
	href="<txp:site_url/><txp:if_variable name="this-section_list-item" value="default"><txp:else/><txp:section/>/</txp:if_variable>"<txp:if_section name='<txp:section/>'>
	class="active"</txp:if_section>>
		<txp:section title="1"/>
</a>

This tag checks to see if the current section_list item (AKA <txp:section/>) is identical to the current section being browsed (the criteria of if_section). If so, this item gets an “active” class attribute (but you can name it whatever you want).

Now the output of your section_list should be identical to the first example. That’s right: we’ve come full circle, but it was worth it! We are only one step away from giving the active class to your “sub-sections”!

Remember your variable from before?

<txp:variable name="this-section_list-item">
	<txp:section/>
</txp:variable>

Using this variable in tandem with if_section is the final step to activate a juicy “active” class for the “parent” section of any “sub-sections” you define. Put this in your anchor element directly after closing your previous if_section conditional:

<txp:if_variable name="this-section_list-item" value="my-parent-section">
	<txp:if_section name="sub-section-1,sub-section-2,etc.">
		class="active"
	</txp:if_section>
</txp:if_variable>

Your final markup will look something like this:

<txp:section_list
	break="li"
	default_title="Home"
	include_default="1"
	sections="about,articles,news,etc,etc,etc"
	wraptag="ul"><txp:variable name="this-section_list-item"><txp:section/></txp:variable><a href="<txp:site_url/><txp:if_variable name="this-section_list-item" value="default"><txp:else/><txp:section/>/</txp:if_variable>"<txp:if_section name='<txp:section/>'> class="active"</txp:if_section><txp:if_variable name="this-section_list-item" value="my-parent-section"><txp:if_section name="sub-section-1,sub-section-2,etc."> class="active"</txp:if_section></txp:if_variable>>
			<txp:section title="1"/>
	</a></txp:section_list>

Good luck!

1 The sample markup assumes you’re “Permanent Link Mode” is set to /section/title in Textpattern’s preferences. You may use whatever permanent link mode suits your site.

2 Markup and attributes nested and indented for clarity.

1 Comment Comment feed

  • Benoit Pontbriand
  • 13 December 2009

Thank you John! I’ve been trying to implement something similar for category_list (with not much luck so far), so I’ll take a hard look at your tip.

Add a comment

Use Textile help to style your comments