Documentation

Light-weight, fast, simple and powerful!
Share This
Translations of this page?:

Introduction

This is another personal test page of mvdkleijn.

Let's try to create an ODT export ready “book” by including a number of navigation cookbook pages.

The recipes below are included from other pages. This is just an inclusion test.

Recipe: Simple submenus in the sidebar

This is a basic form of a submenu for any page that is at level 1 (in other words, the parent page is “Homepage”). There is a full commentary of this code below.

<ul id="nav_sub">
<?php foreach ($this->children() as $child): ?>
    <li><?php echo $child->link($child->title, (url_start_with($child->url) ? ' class="current"': null)); ?></li>
<?php endforeach; ?>
</ul>

You will need to work up some CSS for the nav_sub id, of course.

Code Commentary

For those who are new to Wolf, or its style of coding, here is a line-by-line explanation of this menu, working from the outer layers towards the middle:

1. First there is the the outer Unordered List tags (of course!), with a default CSS ID of #nav_sub (but you can use whatever you like):

<ul id="nav_sub">
 ...
</ul>

2. Next comes the “foreach” frame:

<?php foreach ($this->children() as $child): ?>
 ...
<?php endforeach; ?>

That is asking for all the “children” pages to the current page object (indicated by $this->) to be cycled through, one at a time. As each of the children pages is cycled through, its value is held by the variable $child.

3. Each child page then gets returned as a list item:

<li> ... </li>

Inside the List tags, a lot of work gets done! Again, we'll work from the outside in:

4. Most simply, there is simply a link for the child page being echoed:

<?php echo $child->link( ... ); ?>

5. But the link() function can take two arguments in the ( … ) area: (1) different TEXT for your link (the default is simply to give the title), and (2) any other link parameter you wish to add. However, if you want to add an additional parameter (#2), you must also give a value for the title (#1).1)

That explains the lengthy text inside the child->link(...) function here. We want to add conditional styling, a “current” class, if that child page is the active one. But that also means specifying the title. Since that's the first argument (#1, in the paragraph above), we start there:

<?php echo $child->link($child->title, ... ); ?>

6. In order to style our menu, we need to test to see whether our $child value matches the currently displaying page. That test is found in this code:

(url_start_with($child->url) ? ' class="current"': null)

(The test being used here is Wolf's url_start_with function.) This uses a compact conditional format for PHP, which in “English” could be represented as:

if_this(is_the_case) ? then do this if true : but do this if false ;

So our menu “class-current” test could be written in English: if the URL now showing begins with the same URL as the current $child, then output my class=“current” text, but if it is not the current URL, then don't give me anything (“null”).

That whole test is given as the second argument for the child->link(...) function:

<?php echo $child->link($child->title, (url_start_with($child->url) ? ' class="current"': null)); ?>

7. And that completes the code commentary!

Recipe: Unlimited levels and children

This is a recursive function that allows the user to display an unlimited number of levels and children in a static menu. It also allows you to limit the number of children that are displayed for particular pages. This is achieved with an array of slug/limit pairs. The function's options are:

  1. required, The page from where you want to start displaying the menu;
  2. required, The current page;
  3. optional, If true, start with a <UL>
  4. optional, An array of slug/limit pairs where limit is the maximum number of children to display for that particular slug.
<?php
function displayChildren($page, $current, $startmenu = true, $limits = null) {
  if ($limits != null && array_key_exists($page->slug, $limits)) {
    $arr = array('order' => 'position ASC, published_on DESC', 'limit' => $limits[$page->slug]);
  } else
    $arr = array('order' => 'position ASC, published_on DESC');
  if ($page && count($page->children()) > 0) {
    echo ($startmenu) ? '<ul>' : '';
    foreach($page->children($arr) as $menu) :
        echo '<li'.(in_array($menu->slug, explode('/', $current->url)) ? ' class="current"': null).'>'.$menu->link($menu->title);
        displayChildren($menu, $current, true, $limits);
        echo '</li>';
    endforeach;
    echo ($startmenu) ? '</ul>' : '';
  }
}
?>

Just add the above function to a Snippet or Layout. Then you can use the following code on a page somewhere to produce the actual menu:

<h1>Menu</h1>
<?php
  $page = $this->find('/');
  echo '<ul class="sidemenu">';
  echo '<li>'.$page->link($page->title, (in_array($page->slug, explode('/', $this->url)) ? ' class="current"': null)).'</li>';
  echo displayChildren($page, $this, false, array('articles' => '3', 'a-sub-page' => '1'));
  echo '</ul>';
?>

Recipe: Sitemap-like navigation for Sub-areas

You may wish to have sidebar navigation to the pages for each “main” or “top” page (i.e., child-of-homepage) in your site. This system “automates” such menus, no matter how many “top” pages you have or delete, and no matter how deep the navigation is below them. Here's how:

1. Make this snippet; call it, e.g., sitemap_nav:

<?php
function nav_sitemap($parent)
{
    $out = '';
    $childs = $parent->children();
    if (count($childs) > 0)
    {
        $out = '<ul>';
        foreach ($childs as $child)
            $out .= '<li>'.$child->link().nav_sitemap($child).'</li>';
        $out.= '</ul>';
    }
    return $out;
}
?>
<?php $topSlug = explode('/', $_SERVER['REQUEST_URI']); $areaSlug = $topSlug[1] ?>
 
<div id="sitemap_nav">
<?php if ($areaSlug == 'sitemap' || $areaSlug == '') {
  // put what to do if on Homepage or Sitemap here; current default is to do nothing
} else {
  echo '<p><strong><a href="'. URL_PUBLIC .'" title="Home" >Home Menu</a></strong></p>';
  echo '<p><strong>'.$this->find($areaSlug)->link().'</strong></p>'; // = Top of sub-area
  echo nav_sitemap($this->find($areaSlug)); } 
?>
</div>

2. In your Layout, add the following code in your sidebar <DIV>:

<!-- start sitemap nav -->
<?php $this->includeSnippet('sitemap_nav'); ?>
<!-- end sitemap nav -->

(You can omit the comment lines, of course!) And that's it.

Notes

  1. By default, this code puts nothing on your homepage or sitemap page (if you have one; and if you do, this code will not break your sitemap page).
  2. If your Wolf site is in a subdirectory (e.g. www.example.com/wolf/), then change $topSlug[1] to $topSlug[2] .
  3. It is possible that not using mod_rewrite (thus leaving a ”?” in the URL), or using a URL suffix (e.g., .html), will throw off the search for the slug!
  4. The code is a bit more verbose than it needs to be; this is to keep the layout choices a little more clear. Alter these to suit your own preferences. In particular, you might want to remove the “Home Menu” line, i.e., next line after } else {
  5. This is somewhat like mvdkleijn's “Unlimited levels and children” system (above), but it lacks the control that his system gives you over certain aspects of the navigation.

Recipe: Multi-level collapsing navigation

This code should be saved to a snippet, and then the snippet called in the layout. It works to any level of page depth, and does not get confused by slug names.

<?php
 
function stackup($page, $level, &$astack)
  {
  $ancestor = $page->parent;
  if ($ancestor)
    {
    $astack[$level + 1] = $ancestor;
    stackup($ancestor, $level + 1, $astack);
    }
  }
 
function unstack($current, $max, $stack)
  {
  $here = $stack[$current];
  $next = $stack[$current + 1];
  $childs = $here->children();
  $count = count($childs);
  if ($count > 0)
    {
    echo '<ul>'."\n";
    foreach ($childs as $child)
      {
      if ($child->breadcrumb == $next->breadcrumb)
        {
        echo '<li>'.$child->link('', 'class="current"')."\n";
        if ($current < $max) {
          unstack($current + 1, $max, $stack);
          echo '</li>'."\n";
          }
        else echo '<li>'.$child->link().'</li>'."\n";
        }
      else echo '<li>'.$child->link().'</li>'."\n";
      }
    echo '</ul>'."\n";
    }
  }
 
$astack[0] = $this;
stackup($this, 0, $astack);
$bstack = array_reverse($astack);
$lev = count($bstack) - 1;
if ($lev == 0) echo '<ul><li>'.$bstack[0]->link('', 'class="current"')."\n";
else echo '<ul><li>'.$bstack[0]->link()."\n";
unstack(0, $lev, $bstack);
echo '</li></ul>'."\n";
 
?>

Usage note

This navigation isolates the “Homepage” (or whatever you have called the root page in Wolf) on its own level. To make “Homepage” and the other top-level entries appear on the same level, you can use CSS like this:

#sidenav ul {
 padding: 0 0 0 0px;
 margin: 0;
 list-style-type: none;
}
#sidenav ul ul ul {
 padding: 0 0 0 10px;
 margin: 0;
 list-style-type: none;
}

The first <ul> has zero left padding and so does the second <ul>, but the third and subsequent levels get 10px each (ie. 10px for the 3rd, 20px for the 4th, etc).

[HT: peter_b ]

Recipe: Four-level collapsing menu

The Stacking-Collapsing Nav recipe should be used in preference to this code, but it is retained in the wiki as it still demonstrates some useful techniques.

Unlike the sitemap-style nav, this menu provides up to four-levels of navigation (not unlimited), but it expands/collapses depending on the children of the current page. For example, this menu:

  • Home
  • Classical
  • Jazz
  • Rock

could expand to this, if you click on “Classical”:

  • Home
  • Classical
    • Renaissance
    • Baroque
    • Romantic
  • Jazz
  • Rock

It works up to four levels, or graphically:

  • Top 1
    • Child 2
      • Grandchild 3
        • Great-granchild 4

or in terms of URL structure: http://www.example.com/top/child/grandchild/great-grandchild

Here is the code; some notes are below.

<?php $subPageId = explode('/', $_SERVER['REQUEST_URI']); $level2=$subPageId[1]; $level3=$subPageId[2]; $level4=$subPageId[3]; ?>
 
<h3>Navigation</h3>
 
<ul><!-- top level {1} = main nav -->
<li><a<?php echo url_match('/') ? ' class="current"': ''; ?> href="<?php echo URL_PUBLIC; ?>">Home</a></li>
<?php foreach($this->find('/')->children() as $menu): ?>
<li><?php echo $menu->link($menu->title, (in_array($menu->slug, explode('/', $this->url)) ? ' class="current"': null)); ?>
 
	<?php if ($level2 != '' && strpos($_SERVER['REQUEST_URI'],$menu->slug) == true) : ?>
	<?php $page2 = $this->find($level2); ?>
 
	<ul><!-- child level {2} -->
	<?php foreach ($page2->children(array()) as $menu2): ?>
	<li><?php echo $menu2->link(); ?>
 
		<?php if ($level3 != '' && strpos($_SERVER['REQUEST_URI'],$menu2->slug) == true) : ?>
		<?php $page3 = $this->find($level2.'/'.$level3); ?>
 
		<ul><!-- grandchild level {3} -->
		<?php foreach ($page3->children(array()) as $menu3): ?>
		<li><?php echo $menu3->link(); ?>
 
			<?php if ($level4 != '' && strpos($_SERVER['REQUEST_URI'],$menu3->slug) == true) : ?>
			<?php $page4 = $this->find($level2.'/'.$level3.'/'.$level4); if (count($this->find($level2.'/'.$level3.'/'.$level4)->children()) > 0) : ?>
 
			<ul><!-- great-grandchild level {4} -->
			<?php foreach ($page4->children(array()) as $menu4): ?>
			<li><?php echo $menu4->link(); ?></li>
			<?php endforeach; ?>
			</ul>
			<?php endif; endif; ?>
 
		</li>
		<?php endforeach; ?>
		</ul>
		<?php endif; ?>
 
	</li>
	<?php endforeach; ?>
	</ul>
	<?php endif; ?>
 
</li>
<?php endforeach; ?> 
</ul>

Notes

  • This code might not be very efficient! Suggestions on the forum for improving it are welcome.
  • N.b. It does not work with URL suffixes.
  • The “explode” in the first line is the key to the variables, and the version here assumes Wolf is in the root of your site (e.g., www.mywolfsite.com/), not a subdir (e.g., www.mywebsite.com/wolf/). If your Wolf site is in a subdirectory, then increase the value in each of the square brackets by 1 (e.g., $subPageId[1] becomes $subPageId[2], [2] goes to [3], etc.).
  • If you only need three levels of navigation, just strip out the middle 9 lines (8 code + 1 blank) most deeply indented in the middle of the code, from
    <?php if ($level4 != ''...

    to the double endif line.

  • Because this code is bulky, it is probably easiest to create a snippet for it (e.g. collapsing-nav, and then put it in the sidebar of your homepage using
<?php $this->includeSnippet('collapsing-nav'); ?>

.

Recipe: "Rolling" navigation in sidebar

This system works to any depth of levels you choose to use, but it only gives the navigation from the current page. It is “navigation lite”; it will always point from the current page “up” to its parent (if there is one), and always point “down” from the current page to its children (if there are any). It offers a nice secondary navigation system, complementing the main top-level navigation that Wolf gives by default. The menu looks something like this:

Classical

Baroque
Bach
Telemann
Vivaldi

Use this code in your site’s layout: it will not work as an “inherited” snippet. You can either put this code in the layout itself, or make a snippet for it, but call the snippet, e.g.,

<?php $this->includeSnippet('extra_nav') ?>

in the layout. Include it inside the sidebar DIV, probably best at the top, but you can put it anywhere you like:

<!-- START SUBNAV SYSTEM -->
<p>
<?php if ($this->level() != 0) { echo $this->parent->link($this->parent->title()).'<br />&#8593;<br />'; } ?>
<?php echo $this->title(); ?>
  <?php
    if (count($this->children()) > 0 && $this->title() != 'Articles') {
      echo '<br />';
      foreach($this->children() as $subMenu):
        echo '&#8627;&nbsp;'.$subMenu->link($subMenu->title, (in_array($subMenu->slug, explode('/', $this->url)) ? ' class="current"': null)).'<br />';
      endforeach;
    };
    echo (count($this->children()) > 0 && $this->slug() == 'articles') ? '<br />&#8595;' : '';
  ?>
</p>
<!-- END SUBNAV SYSTEM -->

This menu system:

  1. checks to see whether you are “Home”, in which case the “upward” navigation is omitted;
  2. checks to see whether it is your “Articles” page,2) and if it is, points only to the Monthly Archives which are (by default) beneath it;
  3. prints the current page title (unlinked, of course);
  4. lists all the subpages to the current page with links.

You can always change the arrows/layout, etc., as you please. Note that this approach does not use a <ul>, but just a series of <br />’s.

Recipe: Inline (horizontal) navigation

This is simply a horizontal variation of the preceding (vertical) “recipe”. Again, use this code in your site’s layout (it will not work as an “inherited” snippet). Also like the preceding example, it will always point from the current page “left” to its parent (if there is one), and always point “right” from the current page to its children (if there are any).

Classical ← Baroque → Bach | Telemann | Vivaldi |

One difference from the preceding is that if the current page is “Articles”, then it will point at monthly archive links produced by the navigation code itself, and not the sidebar's default archive listing.

<!-- START INLINE NAV -->
<?php $post = $this->find('articles'); ?>
<?php $all_posts = $post->archive->archivesByMonth(); ?>
 
<div id="inlineNav">
    <p>
    <?php if ($this->level() != 0) { echo $this->parent->link($this->parent->title()).' &#8592; '; } ?>
        <?php echo $this->title(); ?> 
        <?php if (count($this->children()) > 0 && $this->title() != 'Articles') {
            echo ' &#8594; ';
            foreach($this->children() as $inlineMenu):
            echo ''.$inlineMenu->link($inlineMenu->title, (in_array($inlineMenu->slug, explode('/', $this->url)) ? ' class="current"': null)).'&nbsp;|';
            endforeach;
        };
    if ($this->children() > 0 && $this->slug() == 'articles') {
	echo '&#8594; ';
	foreach ($all_posts as $post_date):
	echo '<a href="'.$this->url.'/'.$post_date.URL_SUFFIX.'"> '.strftime('%B %Y', strtotime(strtr($post_date, '/', '-'))).'</a>&nbsp;|';
	endforeach;
    }
    ?>
    </p>
</div><!-- end #inlineNav -->
<!-- END INLINE NAV -->

This codes functions just the same as the "Rolling Vertical" navigation, except for the variation with the monthly archive listing for “Articles”: if you have changed the name of your Articles page to “News” (or whatever), you will need to change the all the occurrences of “A/articles” in the subnav code to the new name (e.g. N/news).

1) If you only want to give different link text, you do not need to add the “any other parameter” value.
2) If you have changed the name of your Articles page to “News” (or whatever), you will need to change the all the occurrences of “A/articles” in the subnav code to the new name (e.g. N/news).
 
user/mvdkleijn/another_test_page.txt · Last modified: 2011-09-12 00:46 (external edit)
 
Except where otherwise noted, content on this wiki is licensed under the following license:GNU Free Documentation License 1.2
Copyright 2010 wolfcms.org / design by yello studio / Wolf CMS Inside