Jason Byrne 2005-09-26 04:48
I wanted to organize my wiki into strict namespaces and I wasn't fond of the breadcrumbs that showed the recently visited pages. I was pleased to find it was easy to implement "you are here" style breadcrumbs instead. However, I wanted the breadcrumbs for namespaces to link to a namespace index page.
Example:
start > deserts > ice_cream > vanilla
I wanted the ice_cream link to go to deserts:ice_cream:index instead of just deserts:ice_cream (because I wanted the index page to be in the namespace that it is indexing!).
So I tweaked the inc/template.php and added a few keys to conf/local.php for a bit more flexibility in the breadcrumbs and here's what I came up with…
$conf['crumbsep'] = ' → '; // Specifies what separates each breadcrumb $conf['index'] = 'index'; // Sets the name for the index page $conf['removeunderscore'] = 1; // Removes underscore from the displayed breadcrumb links
Replace your tpl_youarehere() function with this:
function tpl_youarehere(){ global $conf; global $ID; global $lang; $parts = explode(':', $ID); print $lang['breadcrumb'].': '; // Always show start page if ($a_part[0] != $conf['start']) { tpl_link(wl($conf['start']), $conf['start'], 'title="'.$conf['start'].'"'); } $page = ''; $last = count($parts); $count = 1; foreach ($parts as $part) { if ($count != $last || $part != $conf['index']) { // Skip start page if already done if ($part == $conf['start']) continue; print $conf['crumbsep']; $page .= $part; // Remove underscores if ($conf['removeunderscores'] == 1) { $part = str_replace('_', ' ', $part); } // Set link variable if ($count == $last) $link = $page; else $link = "$page:" . $conf['index']; // Check if page exists if (file_exists(wikiFN($link))) { tpl_link(wl($link), $part, 'title="'.$link.'"'); } else { // Print link, but mark as not-existing tpl_link(wl($link), $part, 'title="'.$link.'" class="wikilink2"'); } $page .= ':'; } $count++; } }
Going further with the index concept, if there is a link to deserts:ice_cream: (with a colon at the end) by default DokuWiki will strip it off the end. However with one tiny tweak to xhtml.php, it will automatically make it deserts:ice_cream:index.
Add this code after global $ID; in the internallink() function of inc/parser/xhtml.php
// If $id ends in ":" append $conf['index'] to it if (eregi(":$", $id)) { $id = $id.$conf['index']; }
Activate hierarchical breadcrumbs (function tpl_youarehere()) in lib/tpl/default/main.php or your own template
I plan to look at this hack to see if I can integrate some of it for better namespace index usage. I also I want to create a hack where if someone goes to deserts:ice_cream and a page named deserts:ice_cream does not exist to make it check for deserts:ice_cream:index and redirect them there (if it exists) before sending them to the “topic does not exist yet”.
The modified version of the youarehere function proposed here does not take into account the new useheading option. This small modification of the function implements a way of displaying the first header of the page as the pagename otherwise the pagename itself. It's using the p_get_first_heading function (parserutils.php file) and does not parse the namespaces, only the pagename.
— Takashi 2006-05-02 14:44
function tpl_youarehere(){ global $conf; global $ID; global $lang; $parts = explode(':', $ID); print $lang['breadcrumb'].': '; // Always show start page if ($a_part[0] != $conf['start']) { tpl_link(wl($conf['start']), $conf['start'], 'title="'.$conf['start'].'"'); } $page = ''; $last = count($parts); $count = 1; foreach ($parts as $part) { if ($count != $last || $part != $conf['index']) { // Skip start page if already done if ($part == $conf['start']) continue; print $conf['crumbsep']; $page .= $part; // Remove underscores if ($conf['removeunderscores'] == 1) { $part = str_replace('_', ' ', $part); } // Set link variable $name = $part; if ($count == $last){ $link = $page; if($conf['useheading']) { $name = p_get_first_heading($link); if($name == NULL) $name = $part; } } else { $link = "$page:" . $conf['index']; } // Check if page exists if (file_exists(wikiFN($link))) { tpl_link(wl($link), $name, 'title="'.$link.'"'); } else { // Print link, but mark as not-existing tpl_link(wl($link), $name, 'title="'.$link.'" class="wikilink2"'); } $page .= ':'; } $count++; } }
Jason Byrne 2006-11-14 23:48
Thanks for that, Takashi. I wanted to have my breadcrumbs not lowercase so I made a change to capitlize the first letter in each (turn it on in conf/local.php). Also I took out the == 1 in the remove underscores part because it's not necessary. So:
function tpl_youarehere(){ global $conf; global $ID; global $lang; $parts = explode(':', $ID); print $lang['breadcrumb'].': '; // Always show start page if ($a_part[0] != $conf['start']) { tpl_link(wl($conf['start']), $conf['start'], 'title="'.$conf['start'].'"'); } $page = ''; $last = count($parts); $count = 1; foreach ($parts as $part) { if ($count != $last || $part != $conf['index']) { // Skip start page if already done if ($part == strtolower($conf['start'])) continue; print $conf['crumbsep']; $page .= $part; // Remove underscores if ($conf['removeunderscores']) { $part = str_replace('_', ' ', $part); } // Capitalize name if ($conf['capitalizenav']) { $part = ucwords($part); } // Set link variable $name = $part; if ($count == $last){ $link = $page; if($conf['useheading']) { $name = p_get_first_heading($link); if($name == NULL) $name = $part; } } else { $link = "$page:" . $conf['index']; } // Check if page exists if (file_exists(wikiFN($link))) { tpl_link(wl($link), $name, 'title="'.$link.'"'); } else { // Print link, but mark as not-existing tpl_link(wl($link), $name, 'title="'.$link.'" class="wikilink2"'); } $page .= ':'; } $count++; } }
This modification is perfect. Way more usable than the standard “you are here”-function. Hope the changes become part of the core. — Andreas 2006-06-14 18:22
Minor changes to make the tip compatible with dokuwiki-rc2007-05-24
— Thanos Massias 2007-06-15 08:54
Given a current page with the path:
:a:b:c:d
and
$conf['start'] = 'index';
the levels of youarehere are (in order of preference):
The useheading option is also taken into account.
function tpl_youarehere($sep=' » '){ global $conf; global $ID; global $lang; // check if enabled if(!$conf['youarehere']) return false; if ($conf['sepyouarehere']){ $sep = $conf['sepyouarehere']; } $parts = explode(':', $ID); print $lang['youarehere'].': '; //always print the startpage if( $a_part[0] != $conf['start']){ if($conf['useheading']){ $pageName = p_get_first_heading($conf['start']); }else{ $pageName = $conf['start']; } tpl_link(wl($conf['start']),$pageName,'title="'.$pageName.'"'); } $page = ''; $printsepyouarehere = "T"; $countarray = 0; $countarraymax = count($parts); foreach ($parts as $part){ $countarray++; // Skip startpage if already done if ($part == $conf['start']) continue; if($printsepyouarehere == "T"){ print " ".$sep." "; } $printsepyouarehere = "T"; $page .= $part; $pageindex = $page.':'.$conf['start']; if(file_exists(wikiFN($pageindex))){ if($conf['useheading']){ $pageName = p_get_first_heading($pageindex); $partName = $pageName; }else{ $pageName = $pageindex; $partName = $part; } tpl_link(wl($pageindex),$partName,'title="'.$pageName.'"'); }else{ if(file_exists(wikiFN($page))){ if($conf['useheading']){ $pageName = p_get_first_heading($page); $partName = $pageName; }else{ $pageName = $page; $partName = $part; } if ('X'.$pageName == 'X') { $pageName = $page; $partName = $part; } tpl_link(wl($page),$partName,'title="'.$pageName.'"'); }else{ if ($countarray == $countarraymax){ // Print the link, but mark as not-existing, as for other non-existing links tpl_link(wl($pageindex),$part,'title="'.$pageindex.'" class="wikilink2"'); }else{ $printsepyouarehere = "F"; } } } $page .= ':'; } }
If you set
$conf['sepyouarehere']
it will override the youarehere separator hardcoded above.
— Thanos Massias 2006-06-14 19:11
You can see this code in action at http://www.kapagroup.gr/ (the page is in Greek - sorry, but I currently have no publicly available example in English).
Most pages have a path that contains index files at each level. The :news namespace, however is different:
There is a :news:index but no :news:2006:index or :news:2006:05:index pages. Additionaly there are no :news:2006 or :news:2006:05 pages. I want to just hide those namespaces from the youarehere path.
You can see the result in this case at: http://www.kapagroup.gr/news/2006/01/01/index
You can also see what happens when you specify a non-existing page in the URL here:
http://www.kapagroup.gr/does_not_exist. Notice that does_not_exist in the youarehere path but the link points to …:does_not_exist:index (this is the intended behaviour). This is the intended behaviour as I want a namespace-based site where each namespace (except in special cases) has an index page. Clicking on that link gets me to the canonical namespace plus index page that should be created. The same also happens when searching for a term: http://www.kapagroup.gr/?do=search&id=search_term.
However http://www.kapagroup.gr/does_not_exist/does_not_exist_either doesn't append to the youarehere path. This is also intentional as I don't want to skip creating intermediate index pages.
PS: I had to move this section to the bottom of the page as I realised that the positive user comments in the Comments section above might appear to be for it - well they ain't.
— Thanos Massias 2006-06-15 02:44
The solution suggested by Thanos Massias above almost perfectly matches my needs.
If I additionally replace
// Skip startpage if already done
if ($part == $conf['start']) continue;
with
// Skip startpage if already done
if ($part == $conf['start'] || $ID == $conf['start'] ) continue;
in his code, when his solution is even compatible with the Basic Multilanguage Support for local.php.
— Clemens Ender 2006-07-11 15:51
— Michael Hundred 2006-08-23 15:06
It works this way.
When it writes a link for the youarehere section, it checks if there is the page. If the check fails it looks for a $conf['start'] page for that namespace. If there is an index it writes the link for that page (also using the heading option if enabled).
I've only added the $page_started variable for the namespace index and an if for the check.
Just replace the tpl_youarehere() function with this one:
function tpl_youarehere(){ global $conf; global $ID; global $lang; //check if enabled if(!$conf['youarehere']) return; $parts = explode(':', $ID); print $lang['youarehere'].': '; //always print the startpage if( $a_part[0] != $conf['start']){ if($conf['useheading']){ $pageName = p_get_first_heading($conf['start']); }else{ $pageName = $conf['start']; } tpl_link(wl($conf['start']),$pageName,'title="'.$pageName.'"'); } $page = ''; foreach ($parts as $part){ // Skip startpage if already done if ($part == $conf['start']) continue; print ' » '; $page .= $part; $page_started=$page; if(!file_exists(wikiFN($page))&&(file_exists(wikiFN($page.':'.$conf['start'])))){ $page_started.=':'.$conf['start']; } if(file_exists(wikiFN($page_started))){ if($conf['useheading']){ $pageName = p_get_first_heading($page_started); $partName = $pageName; }else{ $pageName = $page_started; $partName = $part; } tpl_link(wl($page_started),$partName,'title="'.$pageName.'"'); }else{ // Print the link, but mark as not-existing, as for other non-existing links tpl_link(wl($page_started),$part,'title="'.$page_started.'" class="wikilink2"'); //print $page; } $page .= ':'; } }