Modified it a bit to fit my needs, but someone might find it useful as well.
Basically, I added a 'first' and 'last' class to the first and last item of each level and also added an exclusion list, so that pages with certain templates can have their children excluded.
The usage is:
$treeMenu = $modules->get("MarkupSimpleNavigation"); // load the module
echo $treeMenu->render( $options, $exclusions, $page, $rootPage);
The $exclusions is an array that contains the name of the template of a page which we don't want to see its children. For example if we have a 'News' page with a template of 'news-list' that aggregates a list of article pages with template 'news-article', then 'news-list' should be added in the $exclusions array. I hope that's clear. Not sure if this is the most flexible way to do this, but it works for me right now and I'm sure someone will come along and improve on it!!
One other change was that I removed the newlines from the <li>'s to make the menu code easier to read and also I've changed the $childs to $children just because it bugged me... sorry!!
I haven't tested the module extensively (read: at all) and as I mentioned in a previous post I'm not really a PHP coder (or a web dev for that matter!) so bear that in mind when you read the few lines that I changed!!!
<?php
/**
*
* Simple Tree Menu Module 1.0.0
*
* @author Soma, with code based by Apeisa, Ryan.
*
* @date_created 08/03/2012
* @last_modified 08/03/2012
*
* ProcessWire 2.x
* Copyright (C) 2011 by Ryan Cramer
* Licensed under GNU/GPL v2, see LICENSE.TXT
*
* http://www.processwire.com
* http://www.ryancramer.com
*
*/
class MarkupSimpleNavigation extends WireData implements Module {
public static $defaultOptions = array(
'css_parent' => 'parent',
'css_current' => 'current',
'css_levels_on' => false,
'collapsed' => false,
'show_root' => false,
'ul_id' => '',
'ul_class' => '',
'max_levels' => null
);
public static function getModuleInfo() {
return array(
'title' => "Markup for simple nested navigation",
'summary' => 'Module to render simple nested ul tree of the site structure. See readme for usage and options avaiable.',
'version' => 100,
'href' => 'http://processwire.com/talk/topic/1036-markupsimplenavigation/',
'autoload' => false,
'singular' => true
);
}
public function init() {
//$this->fuel->set('treeMenu', $this );
$this->set('iteration',0);
}
/**
*
* Main method called ony pages by echo $treeMenu->render(); to render
* init tree rendering, merge options with defaults
*
*/
public function render( Array $options = null, Array $exclusions = null, Page $page = null, Page $rootPage = null ) {
if($options != null && is_array($options)){
$options = array_merge(self::$defaultOptions, $options);
} else {
$options = self::$defaultOptions;
}
return $this->_renderTree( $options, $exclusions, $page, $rootPage );
}
/**
*
* Render the tree method
*
*/
private function _renderTree( $options, $exclusions, $page, $rootPage ){
$this->iteration++;
if(is_null($page)) $page = wire('page');
if(is_null($rootPage)) $rootPage = wire('pages')->get('/');
$ul_class = '';
$ul_id = '';
if($options['ul_class'] != '') $ul_class = " class='".$options['ul_class']."'";
if($options['ul_id'] != '') $ul_id = " id='".$options['ul_id']."'";
if($this->iteration == 1) $out = "\n<ul$ul_class$ul_id>";
else $out = "\n<ul>";
$parents = $page->parents;
if($options['show_root'] && $this->iteration == 1) {
$children = $rootPage->children;
$children->prepend( $rootPage );
} else {
$children = $rootPage->children;
}
foreach($children as $key=>$child) {
$s = '';
$level = ($child === $rootPage) ? 1 : count($child->parents);
if($options['css_levels_on']) $class = " level-" . $level;
else $class = '';
$template = $child->template;
if ( !in_array($template->name, $exclusions) ) {
if(!$key) $class .= " first";
if($key == (count($children) - 1 ) ) $class .= " last";
if($options['max_levels'] != null && $level >= $options['max_levels']) $stopit = true;
else $stopit = false;
if(!$options['collapsed']){
if($parents->has($child)) {
$class .= ($child !== $rootPage) ? " " . $options['css_parent'] : '' ;
}
else if($child === $page){
$class .= " " . $options['css_current'];
}
if($child->numChildren && $child !== $rootPage){
if(!$stopit) {
$s = str_replace("\n", "\n\t\t", $this->_renderTree($options, $exclusions, $page, $child));
}
}
}
else
{
if($child->numChildren && $parents->has($child)) {
$class .= ($child !== $rootPage) ? " " . $options['css_parent'] : '' ;
if(!$stopit) {
$s = ($child !== $rootPage) ? str_replace("\n", "\n\t\t", $this->_renderTree($options, $exclusions, $page, $child)) : '';
}
} else if($child === $page) {
$class .= " " . $options['css_current'];
if($page->numChildren && $child !== $rootPage) {
if(!$stopit) {
$s = str_replace("\n", "\n\t\t", $this->_renderTree($options, $exclusions, $page, $child));
}
}
}
}
$class = substr($class,1);
if(strlen($class) > 0) {
$class = " class='$class'";
}
}
$out .= "\n\t<li><a$class href='{$child->url}'>{$child->title}</a>$s</li>";
}
$out .= "\n</ul>\n";
return $out;
}
}