Bookstyle navigation
A common navigation aid in documentation web pages or long articles is the 'prev' and 'next' button. This tutorial describes one approach to such a navigation system in Ariadne.
For this tutorial we want to design a navigation system which will display in each page a link to the previous and next page on the same level. Suppose we have a book with multiple chapters, then the last page of a chapter should point to the index page of the next chapter via the 'next' link, and the first page should link to the index page of the previous chapter via the 'previous' link. In all other cases the 'next' and 'previous' links should behave as you would expect, based upon the order of the pages indicated by their priority and their alfabetical ordering.
We'll start with defining the structure of the book. The book is contained in a single directory (pdir). Each chapter is a separate subdirectory of the book (pdir again). Each page is a page (ppage) in it's chapters subdirectory. e.g.:
/book/chapter1/page1/ /book/chapter1/page2/ /book/chapter2/page1/ /book/chapter2/page2/
For the indexes of the book and each chapter, all we need is a single default
template (view.html
) which displays a list of
children. e.g.
<html> <head> <title><pinp> echo $nlsdata->name; </pinp></title> </head> <body> <h1><pinp> echo $nlsdata->name; </pinp></h1> <pinp> if ($nlsdata->summary) { echo "<p><i>".$nlsdata->summary."</i></p>"; } </pinp> <ol> <pinp> ls("show.html"); </pinp> </ol> </body> </html>
This template is defined for 'pdir' at /book/
as default. We'll also need a 'show.html
'
template to list each child:
<li><a href="<pinp> echo make_url(); </pinp>"><pinp> echo $nlsdata->name; </pinp></a></li>
This template is defined for 'ppage' at /book/
, also as default:
As pdir inherits from ppage, this template will also be used to generate the list of chapters at the top level of the book.
The next step is the default view template for each page. This template must
show the the title, summary and full text of the page, and also show links to
the previous and next page. From the context of a page, the previous or next
page is not a child or parent, but a sibling. To access the siblings we
need to go through the parent. So first we create a template that will try to
figure out which pages are the previous and next, given a specific
current page. We'll call this template 'get.prevnext.html
'. This template is defined on
'pdir', as the page will call this template on it's parent, which should be a
pdir.
The first step is to get a list of all pages, in order. Since we've chosen to use the default ordering scheme used by Ariadne, that part is easy:
<pinp> $current=getvar("current"); $list=ls("system.get.phtml");
In $list
there is now a complete list of all
direct children of the directory, including their data. $current
contains the path of the page that called this template.
So the next step is to walk through the list of children untill we find the object with the same path as $current:
while (list($key, $object)=each($list)) { if ($object->path==$current) { $object=current($list); if ($object) { $next=$object->path; $next_name=$object->nlsdata->name; } $prev=$temp; $prev_name=$temp_name; break; } else { $temp=$object->path; $temp_name=$object->nlsdata->name; } }
This code will loop through the list of objects untill the object
corresponding with $current is found. Then it sets the variables $next
, $next_name
,
$prev
and $prev_name
to the path and name values of the preceding and following objects
respectively. The line '$object=current($list)
'
will actually get the next object from the list, as each()
will silently move the current index pointer to
the next element of an array after retrieving an element from it.
If you look closely to this code, you will notice that if $current
is the first and/or the last page of a
chapter, $prev
and/or $next
will be empty. In this case the template
continues to search for either the previous or next chapter:
if ((!$prev || !$next) && $path!='/book/') { get($parent, "get.prevnext.html", Array("current" => $path)); if (!$prev) { $prev=getvar("prev"); $prev_name=getvar("prev_name"); } if (!$next) { $next=getvar("next"); $next_name=getvar("next_name"); } }
This code will recursively call get.prevnext.html
in it's parent (untill the
top level defined for the book, in this case /book/) and retrieve the values for $next
and/or $prev
from there, if possible.
Finally we need to return these values to the calling template:
putvar("next",$next); putvar("next_name",$next_name); putvar("prev",$prev); putvar("prev_name",$prev_name); </pinp>
So given this useful template, the view.html for ppage will look something like this:
<html> <head> <title><pinp> echo $nlsdata->name; </pinp></title> </head> <body> <h1><pinp> echo $nlsdata->name; </pinp></h1> <pinp> get($parent, "get.prevnext.html", Array("current" => $path)); $next=getvar("next"); $prev=getvar("prev"); $next_name=getvar("next_name"); $prev_name=getvar("prev_name"); echo "<table width=\"100%\" border=\"0\"><tr>"; if ($prev) { echo "<td valign=\"top\">< <a href=\"". make_url($prev)."\">$prev_name</a></td>"; } if ($next) { echo "<td valign=\"top\" align=\"right\">"; echo "<a href=\"".make_url($next)."\">$next_name</a> ></td>"; } echo "</tr></table>"; if ($nlsdata->summary) { echo "<p><i>".$nlsdata->summary."</i></p>"; } ShowPage(); </pinp> </body> </html>
Remember that $next
and/or $prev
may be empty after the call. In that case we
should not try to print a link.