Jump to content

Adding a second level to Menu


Neo
 Share

Recommended Posts

I basically just got started with ProcessWire, followed the beginners tutorials and just try to implement a test site using the beginners template.

My PHP knowledge is limited, so please bear with me.

What I am trying to achieve is implement a second level for the menu resembling the following html structure:

<ul class="menu" id="responsive">

	<li><a href="index.html" id="current"> Home</a></li>

	<li><a href="about.html"> About</a>

	<li><a href="#"> Services</a>
		<!-- Second Level / Start -->
		<ul>
			<li><a href="service1.html">Service 1</a></li>
			<li><a href="service2.html">Service 2</a></li>
			<li><a href="service3.html">Service 3</a></li>
			<li><a href="service4.html">Service 4</a></li>
		</ul>
		<!-- Second Level / End -->
	</li>

	<li><a href="#"> Portfolio</a>

</ul>

Following the example in the beginners template, I managed to get the first level going:

<ul class="menu" id="responsive"><?php

	// top navigation consists of homepage and its visible children
	$homepage = $pages->get('/'); 
	$children = $homepage->children();

	// make 'home' the first item in the navigation
	$children->prepend($homepage); 

	// render an <li> for each top navigation item
		foreach($children as $child) {
			if($child->id == $page->rootParent->id) {
				// this $child page is currently being viewed (or one of it's children/descendents)
				// so we highlight it as the current page in the navigation
				echo "<li><a href='$child->url' id='current'>$child->title</a></li>";
			} else {
				echo "<li><a href='$child->url'>$child->title</a></li>";
			}
		}
?></ul> 

However, I am struggeling with the the second-level.

Would appreciate your guidance. 

Link to comment
Share on other sites

Here is the code I use for at least one website for the moment. I don't remember exactly where in the forum(s) or in which profile I found it.

I don't remember if it was one, or if I merged two pieces of code (perhaps I added the first "<li>").

It could be a start.

(I'm also a php beginner.)

<!-- Horizontal Menu -->
	    <ul class="menu"><li><a href="<?=$config->urls->root?>"><?=$pages->get('/')->title?></a></li><?php 
		
		    function topMenu($currentPage, $startPage) {
			    $out = '';
			    foreach($startPage->children as $page) {
				    $class = '';
				    if($currentPage->id == $page->id) $class =  " class='current'";
				    $out .= "<li$class><a href='$page->url'>$page->title</a>";	
				    if(count($page->children)) {
					    $out .= "<ul>" . topMenu($currentPage, $page, $level+1) . "</ul>";
				    }
				    $out .= "</li>";
			    }
			    return $out; 
		    }

		    echo topMenu($page, $pages->get('/')); 

	    ?></ul>
Link to comment
Share on other sites

I finally ended up using the recommended Markup Simple Navigation module, which is probably the cleanest and most customizable solution without reinventing the wheel.

Thanks a lot.

Link to comment
Share on other sites

It's not good to reinvent the wheel, but it's not bad to know how wheels are made. What you want to do is actually quite simple, and all you need is a loop inside the first loop. For only two levels, a very simplified version could look like this:

echo "<ul>";
foreach($homepage->children as $item) { // loop through the children of root
    echo "<li><a href='$item->url'>$item->title</a>";
        if ($item->numChildren(true)) { // check if this item has children
            echo "<ul>";
                foreach($item->children as $sub_item) { // loop through the children of each item
                    echo "<li><a href='$sub-item->url'>$sub_item->title</a></li>";
                }
            echo "</ul>";
        }
    echo "</li>";
}
echo "</ul>";

For more levels, you could keep adding loops inside loops, but then, it would make more sense to make a recursive function (a function that calls itself while there still are children).

One more thing. In your code you add the id for the current page like this:

if($child->id == $page->rootParent->id) {
    // this $child page is currently being viewed (or one of it's children/descendents)
    // so we highlight it as the current page in the navigation
    echo "<li><a href='$child->url' id='current'>$child->title</a></li>";
} else {
    echo "<li><a href='$child->url'>$child->title</a></li>";
}

You can avoid repeating code by doing this instead:

if($child->id == $page->rootParent->id) {
    $current = ' class="current"';
} else {
    $current = '';
}
echo "<li><a href='$child->url'{$current}'>$child->title</a></li>";

Or, more compact:

$current = $child->id == $page->rootParent->id ? ' class="current"' : '';
echo "<li><a href='$child->url'{$current}'>$child->title</a></li>";

You can also replace $child->id == $page->rootParent->id by $item == $page for the current page and use rootParent to give the class to the parent item only

  • Like 3
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...