Page trees can be created in different ways:

MethodWhen 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:

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

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

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

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:

	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>';
        }
    });
CODE

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.

optioninputnote
contextPathstringSets the origin for rest-calls
renderChildrenUlfunction()Set how children ULs are rendered
renderChildrenLifunction(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
cssobjectObject of key-value pairs for classes used, see below
css.ancestorstringparent items
css.currentstringcurrently viewed item
css.normalstringchildren items
css.expandedstringitem is expanded
css.collapedstringchildren of collapsed trees
css.leafstringchildren of expanded trees

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

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>'
    }
};
CODE

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

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

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

#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>
HTML/XML

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 dynamically loaded page tree. 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:

#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>
XML

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.)

#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>
XML

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

$include.page("_NavigationTree")
CODE

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

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

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