Skip to main content
Skip table of contents

Output a page tree

Page trees can be created in different ways:

Method

When to use it

Lazy-loading trees

You should almost always use this – it offers good performance and usability

Render the page tree dynamically, based on the Confluence page hierarchy

This option is useful for generic themes that should work out of the box, and should be used if you need the tree unfolded at all times

Include page content from a page that contains a (nested) list of links

Use this if you want to configure what is displayed by changing the macro settings in Confluence.

This option offers more flexibility, but requires some more work (users need to create a page with a certain name that is included for the navigation)

By hard-coding it into the template

Simple, but inflexible – not recommended in normal circumstances

Lazy-loading tree 

The lazy-loading tree method is recommended in most scenarios. It offers good performance, and the page tree also remembers which pages are collapsed as you navigate. It's the approach we use in the WebHelp theme that we ship with Scroll Viewport.

You can add a lazy loading tree in Scroll Viewport by adding a REST API that can be used by templates to load children of a specific page. In order to use the REST API, we provide the scrollTree jQuery plugin.

Add a lazy-loading tree using the scrollTree jQuery plugin

  1. Download the scrollTree jQuery Plugin, add it to your theme and load it in the HTML head:

    CODE
    <script src="${theme.baseUrl}/js/jquery.scroll-tree.js"></script>
  2. Add an element where the page tree should be displayed:

    CODE
    <ul class="nav sp-tree"
        data-viewport-id="$viewport.id"
        data-root="$tree.root.link"
        data-current="$page.link">
    </ul>
  3. Initialize the jQuery scrollTree plugin when the document is loaded:

    CODE
    $(document).ready(function () {
        $('.sp-tree').scrollTree({
            'contextPath': '' // this should be adapted to the Confluence instance
        });
    });
    
    

You have now added the lazy-loading tree to your template.

Hide pages

In Scroll Versions, pages with a dot (.) in front of the title are hidden by default. This does not work for the lazy-loaded trees. For this to work, you need to change how list items are rendered.

You can do this by passing a function to the options object:

CODE
	function escapeHtml(input){
		return $('<div />').text(input).html();
	}    
	$('.sp-tree').scrollTree({
        'contextPath': '',
        'renderChildLi': function (child, opts) {
			
            if (child.title.indexOf('.') === 0) {
                return '';
            }
            return '<li class=" + opts.css[child.type] + "><span class="sp-toggle"></span><a href="' + child.link + '">' + escapeHtml(child.title) + '</a></li>';
        }
    });

This script hides all pages starting with a dot in the page title. Instead of rendering the list item, the script returns an empty string. For a list of options to pass, to further overwrite the page tree, see below.

Further customization

There are several more options for customized tree outputs. These are useful, for example, if you are not happy with the classes or with the display of list items.

option

input

note

contextPath

string

Sets the origin for rest-calls

renderChildrenUl

function()

Set how children ULs are rendered

renderChildrenLi

function(child, opts)

Set how children LIs are rendered

propertynote
optsYour options
childthe child element
child.type

Type of item (normal, ancestor, current)
See image for example.

child.linkLink to the page
child.titleTitle of the page


css

object

Object of key-value pairs for classes used, see below

css.ancestor

string

parent items

css.current

string

currently viewed item

css.normal

string

children items

css.expanded

string

item is expanded

css.collaped

string

children of collapsed trees

css.leaf

string

children of expanded trees

These are the default options: (note that there is no normal class)

CODE
function escapeHtml(input) {
	return $('<div />').text(input).html();
}


var DEFAULT_OPTIONS = {
    'contextPath': '',
    'css': {
        'ancestor': 'active',
        'current': 'active',
        "leaf": 'leaf',
        'loading': 'sp-loading',
        'collapsed': 'sp-collapsed',
        'expanded': 'sp-expanded',
        'error': 'sp-error'
    },
    'renderChildrenUl': function () {
        return '<ul class="nav"></ul>';
    },
    'renderChildLi': function (child, opts) {
        return '<li class=" + opts.css[child.type] + "><span class="sp-toggle"></span><a href="' + child.link + '">' + escapeHtml(child.title) + '</a></li>'
    }
};

Creating the page tree dynamically – server-side 

Use this page tree if you need the tree unfolded at all times.

In the page.vm, include the tree template as follows:

page.vm
HTML/XML
$include.template("includes/navigation-tree-entry.vm")

In the folder includes (create one, if it isn't there already), create the file that will recursively render the tree:

includes/navigation-tree-entry.vm
HTML/XML
#macro (createTree $children)
    #foreach($child in $children)
    <li>
        <a href="$child.link">$child.title</a>
        #if ($child.hasChildren)
            <ul>
                #createTree($child.children)
            </ul>
        #end
    </li>
    #end
#end

<ul>
    #createTree($pages.home.children)
</ul>

That's it - Your page will now create a nested list with all pages. Styling the tree is left as an exercise to the reader, as this is always an individual requirement. For bigger page trees, you should use the Output a page tree#lazy. Described further down on this page.

Page tree with levels

If you want to control how many children levels should get rendered in your page tree you can extend the example from above with the following:

XML
#macro ( createTree $children $levels $topLevelClickAble )
    #foreach( $child in $children )
 		<li>
	   		#if( $topClickAble )
 				#if( $child.hasChildren )
       				<span>
          				<a href="$child.link">$child.title</a>
       				</span>
 				#else
 					<a href="$child.link">$child.title</a>
 				#end
 			#else
 				#if( $child.hasChildren )
       				<a>$child.title</a>
 				#else
 					<a href="$child.link">$child.title</a>
 				#end
 			#end
   			#set( $levels = $levels - 1)
 			#if ( $child.hasChildren && $levels > 0 )
    			<ul>
 					#createTree( $child.children, $levels, true )
     			</ul>
 			#end
 		</li>
 	#end
#end

<ul>
    #createTree( $pages.home.children, 2, false )
</ul>

In this example we used two levels for the page tree and the first level is not clickable as a page. If you open the page tree of this documentation, you can have a look on how the tree gets rendered.

Creating a page tree for blog posts

If you want to have the same blog post overview as you see in Confluence, use the code below. (By default, the overview is rendered as 'Blog Posts in Dec 2016'. As this can become quite cluttered, you can replace it with just the full month ('December' in this case) using the following code.)

XML
#set($months = {"Jan":"January", "Feb":"February", "Mar":"March", "Apr":"April", "May":"May", "Jun":"June", "Jul":"July", "Aug":"August", "Sep":"September", "Oct":"October", "Nov":"November", "Dec":"December"})
#macro (createTree $children)
    #foreach($child in $children)
        <li>
            #if ($child.class.name.indexOf('BlogOverviewPagePlaceholder') != -1)
                #set($month = $child.title.replace('Blog Posts in ', ''))
                #set($test = "value")
                #set($isMonthlyOverview = false)
                #foreach($mon in $months.keySet())
                    #if($month.indexOf($mon) != -1)
                        #set($isMonthlyOverview = true)
                        <a href="$child.link">$months.get($mon)</a>
                    #end
                #end
                #if($isMonthlyOverview == false)
                    <a href="$child.link">$month</a>
                #end
            #else
                <a href="$child.link">$child.title</a>
            #end
        #if ($child.hasChildren)
            <ul>
                #createTree($child.children)
            </ul>
        #end
        </li>
     #end
 #end
<ul>
    #createTree($page.children)
</ul>

Creating the page tree from a Confluence page 

Create a page called '_NavigationTree' and create the navigation tree using a nested unordered list or the children macro.

In page.vm (or any other template), include the content of the wiki page:

page.vm
CODE
$include.page("_NavigationTree")

Hard-coding the tree in the template 

This is actually really simple, just create a list of HTML elements and hard-code the links:

page.vm
CODE
<ul>
  <li><a href="/path/to/page-1">Page 1</a></li>
  <li><a href="/path/to/page-2">Page 2</a></li>
</ul>

Of course, this approach is very inflexible, but can be suitable if a quick solution is needed.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.