ProcessWire - Navigation Snippets: Unterschied zwischen den Versionen

Aus Wikizone
Wechseln zu: Navigation, Suche
 
(60 dazwischenliegende Versionen von 11 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
 +
== TODO Seite aufräumen ==
 +
== Siehe auch ==
 +
[[Processwire Module: MarkupSimpleNavigation]] automatisch Navigation aus Seitenbaum erstellen
 +
[[Aligator (ProcessWire)]] - automatische Navigation, gut wenn manipuliert werden muss.
 +
[[Menu Builder (ProcessWire)]] - Menüs im Backend erstellen (Wordpress like)
 +
 +
== Navigation in Pagewire - Einführung ==
 +
=== Navigationstypen allgemein ===
 +
Es gibt verschiedene '''Typen von Navigationen'''. In Processwire hat man ein '''Pages Objekt''', indem auch Zugriff auf Kind- und Elternseiten möglich sind. Es bildet also immer die Sitestruktur ab. Daher übergibt man an die unten aufgeführten Funktionen entweder die Homepage oder die aktuelle Seite.
 +
 +
Unter dem Aspekt auf welcher Seite man sich befindet kann man unterscheiden zwischen:
 +
* '''absolute Navigation''' normalerweise ausgehend von der Rootseite. diese ist dann auf allen Seiten gleich.
 +
** z.B. alle Seiten des ersten Levels stehen in der Hauptnavigation egal auf welcher Seite ich im Moment bin
 +
** z.B. verschachtelte Liste mit 2 oder mehr Leveln für Dropdown Navigationen wie Superfish, Megamenüs (mit zusätzlichen Infos...) oder Bootstrap Navigationen.
 +
** Sitemap
 +
* '''Navigation relativ zur Seite''' Diese kann sich von Seite zu Seite unterscheiden.
 +
** Alle '''Seiten der aktuellen Ebene''' (oft kombiniert mit Breadcrumb / Hier-bin-ich) )
 +
** Hauptebene '''und''' aktueller Level
 +
** Alle Ebenen '''bis zur aktuellen Seite + deren Unterseiten''' falls vorhanden.
 +
In letzten Fall könnte man auch Varianten bauen in denen eine Verschachtelte Liste erzeugt wird aber nur bestimmte Teile absolut Positioniert angezeigt werden und andere versteckt werden. Manchmal möchte man bestimmte Level aber auch an anderer Position zeigen (z.B. Sidebar)
 +
In der Praxis hat man in der Regel
 +
* Mindestens eine Hauptnavigation mit allen Seiten der 1. Ebene oder eine Hauptnavigation mit mehreren Ebenen für Dropdown Navigationen, mobile Navigation oder auch Sitemapartige Navigationen für den Footer (oft mit kleinen Beschreibungen).
 +
* Eine Metanavigation mit Service Seiten wie Kontakt, Impressum etc. oft ist diese im Footer.
 +
 +
=== Unterschiede zwischen Verstecken, Veröffentlichen, Sperren ===
 +
In Processwire sind diese Begriffe mit Userrechten verknüpft. Eine unveröffentlichte Seite kann also durchaus im Frontend aufgerufen werden (es sei denn man regelt das anders.) Vielmehr geht es darum das man User Rollen so gestalten kann, dass man z.B. einem User nur erlaubt unveröffentlichte Seiten zu editieren.
 +
 +
Denoch gibt es auch ein paar weitere Unterschiede.
 +
 +
Gesperrt -> Man kann die Seite nicht zum Editieren aufrufen. Über die Url kann Sie aufgerufen werden.
 +
 +
Unpublished -> Die Seite kann sobald sie gespeichert ist auch aufgerufen werden, WENN der User berechtigt ist. Nicht für Guest User (der normale Viewer)
 +
 +
TODO checken ob die Tabelle so für nicht angemeldete User stimmt.
 +
{| class="wikitable"
 +
|-
 +
!  !! Im Menü ($pages->find) !! Über URL erreichbar($pages->get) !! Ausgabe im Frontend !!
 +
|-
 +
| Unpublished / Unveröffentlicht || Nein || Nur User mit passenden Rechten. Gäste -> leere Seite ||
 +
|-
 +
| Hidden / Versteckt || Nein || Ja || Ja - leere Seite (keine Feldausgabe)
 +
|-
 +
| Locked / Gesperrt || Ja || Ja  || Ja
 +
|-
 +
| Trash || Nein || Nein ||
 +
|}
 +
==== Seiten auf unveröffentlicht stellen ====
 +
https://processwire.com/talk/topic/29-how-to-unpublish-a-page-without-deleting-it/
 +
 +
Was soll man tun wenn man eine Seite tatsächlich nicht mehr anzeigen will, sie aber noch nicht wegwerfen will?
 +
Ryan schlägt folgendes vor:
 +
* Mülleimer
 +
* Remove Guest Role in Template
 +
*
 +
 
== Basics ==
 
== Basics ==
 +
=== Minimal Navigation Bar ===
 +
Aus dem Standard Template
 +
<syntaxhighlight lang="php">
 +
<?php
 +
$homepage = $pages->get("/");
 +
$navigation = $homepage->and($homepage->children)->implode(" / ", "<a href='{url}'>{title}</a>");
 +
?>
 +
<p id="topnav">
 +
  <?= $navigation ?>
 +
</p>
 +
</syntaxhighlight>
 +
 +
=== Basic Navigation ===
 +
<syntaxhighlight lang="php">
 +
<?php
 +
  // get the homepage object
 +
  $homepage = $pages->get("/");
 +
  // get PageArray of homepage object and child page objects
 +
  $navItems = $homepage->and($homepage->children);
 +
?>
 +
Now you have a PageArray with the required items, you can iterate over them one at a time, and print the title of the page and the link to the page itself and wrap the whole thing in your list tag.
 +
 +
<ul class="nav">
 +
 +
<?php
 +
  // get the homepage object
 +
  $homePage = $pages->get("/");
 +
  // get PageArray of homepage object and child page objects
 +
  $navItems = $homePage->and($homePage->children);
 +
  // or if you don't want the home link
 +
  // $navItems = $homePage->children;
 +
  // iterate over the $navItems PageArray
 +
  foreach ($navItems as $navItem):
 +
?>
 +
 +
  <li class="nav-item">
 +
    <a class="nav-link" href="<?php echo $navItem->url; ?>"><?php echo $navItem->title; ?></a>
 +
  </li>
 +
 +
  <?php endforeach; ?>
 +
 +
</ul>
 +
</syntaxhighlight>
 +
 +
==== Basic mit active Class ====
 +
<syntaxhighlight lang="php">
 +
<ul class="nav">
 +
 +
<?php
 +
  // get the homepage object
 +
  $homePage = $pages->get("/");
 +
  // get PageArray of homepage object and child page objects
 +
  $navItems = $homePage->and($homePage->children);
 +
  // or if you don't want the home link
 +
  // $navItems = $homePage->children;
 +
  // iterate over the $navItems PageArray
 +
  foreach ($navItems as $navItem):
 +
 +
// if the id of the page currently being
 +
// iterated equals the id of the current page
 +
$activeClass = ($navItem->id == $page->id) ? " active" : "";
 +
?>
 +
 +
  <li class="nav-item">
 +
    <a class="nav-link<?php echo $activeClass; ?>" href="<?php echo $navItem->url; ?>"><?php echo $navItem->title; ?></a>
 +
  </li>
 +
 +
  <?php endforeach; ?>
 +
 +
</ul>
 +
</syntaxhighlight>
 +
 +
==== Child Menu ====
 +
<syntaxhighlight lang="php">
 +
 +
<ul class="sub-menu">
 +
 +
<?php
 +
  // get children of the parent of the current page
 +
  $childPages = $page->parent->children;
 +
 +
  // iterate over the $navItems PageArray
 +
  foreach ($childPages as $childPage):
 +
 +
  // if the id of the page currently being
 +
  // iterated equals the id of the current page
 +
  $activeClass = ($navItem->id == $page->id) ? " active" : "";
 +
?>
 +
 +
  <li class="nav-item">
 +
    <a class="nav-link<?php echo $activeClass; ?>" href="<?php echo $childPage->url; ?>"><?php echo $childPage->title; ?></a>
 +
  </li>
 +
 +
  <?php endforeach; ?>
 +
 +
</ul>
 +
</syntaxhighlight>
  
 
=== Page Level ===
 
=== Page Level ===
 
In which level in page tree we are?
 
In which level in page tree we are?
 
  $level = count($page->parents);
 
  $level = count($page->parents);
 +
 +
=== Parent, active parent ===
 +
$isParent = $item->hasChildren;
 +
$isActiveParent = $item->child('id='.$page->id)->id; // Seite ist in Rootline wenn sie ein aktives Kind hat
 +
 
=== Link to Subpage und Platzhalter (Spacer) ===
 
=== Link to Subpage und Platzhalter (Spacer) ===
 
Kann man gut für Superfish Menüs etc. benutzen. Bildet das Verhalten von Shortcuts und Spacern aus TYPO3 nach.
 
Kann man gut für Superfish Menüs etc. benutzen. Bildet das Verhalten von Shortcuts und Spacern aus TYPO3 nach.
Zeile 56: Zeile 213:
 
Erzeugt 301 Weiterleitung
 
Erzeugt 301 Weiterleitung
  
Anderer Ansatz wäre evtl. den Link bei der Menügenerierung direkt zu generieren.
+
Anderer Ansatz wäre evtl. den Link bei der Menügenerierung direkt zu generieren. finde ich persönlich besser siehe ''Link to subpage und Platzhalter'' Beispiel. Allerdings sollte man dann vielleicht die Seite trotzdem per 301 Weiterleiten, falls die URL mal direkt aufgerufen wird oder bei Google gelistet ist.
  
==== Redirect anderer Seite in der Navigation ====
+
==== Redirect zu anderer Seite in der Navigation ====
 
https://processwire.com/talk/topic/762-howto-menu-item-that-links-to-another-page/
 
https://processwire.com/talk/topic/762-howto-menu-item-that-links-to-another-page/
  
Zeile 68: Zeile 225:
  
 
4. In your nav-generation code that links to the pages, do something like this:
 
4. In your nav-generation code that links to the pages, do something like this:
 +
 
<syntaxhighlight lang="php">
 
<syntaxhighlight lang="php">
 
<?php
 
<?php
Zeile 79: Zeile 237:
  
 
=== Breadcrumb ===
 
=== Breadcrumb ===
<pre>
+
<syntaxhighlight lang="php">
<!-- breadcrumbs -->
+
<!-- breadcrumbs -->
<div class='breadcrumbs'><?php  
+
<div class='breadcrumbs'>
// breadcrumbs are the current page's parents
+
<?php  
foreach($page->parents() as $item) {
+
// breadcrumbs are the current page's parents
echo "<span><a href='$item->url'>$item->title</a></span> ";  
+
foreach($page->parents() as $item) {
}
+
echo "<span><a href='$item->url'>$item->title</a></span> ";  
// optionally output the current page as the last item
+
}
echo "<span>$page->title</span> ";  
+
// optionally output the current page as the last item
?></div>
+
echo "<span>$page->title</span> ";  
</pre>
+
?>
 
+
</div>
=== Main Level Navigation Bar ===
+
</syntaxhighlight>
Homepage + Kindseiten (1 Level). Die Variable $homepage wird i.d.R. in init.php definiert:
 
$homepage = $pages->get('/');
 
 
 
<pre>
 
<ul class='topnav'><?php
 
// top navigation consists of homepage and its visible children
 
foreach($homepage->and($homepage->children) as $item) {
 
if($item->id == $page->rootParent->id) {
 
echo "<li class='current'>";
 
} else {
 
echo "<li>";
 
}
 
echo "<a href='$item->url'>$item->title</a></li>";
 
}
 
// output an "Edit" link if this page happens to be editable by the current user
 
if($page->editable()) echo "<li class='edit'><a href='$page->editUrl'>Edit</a></li>";
 
?></ul>
 
</pre>
 
  
 +
=== One Level Navigation Bar ===
 +
[[ProcessWire - One Level Navigation]]
 
=== Nächste Seite / Next Page Navigation ===
 
=== Nächste Seite / Next Page Navigation ===
// add next button if there is another page next
+
Beispiel 1
 
<syntaxhighlight lang="php">
 
<syntaxhighlight lang="php">
 
if($page->next->id){
 
if($page->next->id){
Zeile 123: Zeile 265:
 
     </div>';
 
     </div>';
 
}
 
}
 +
</syntaxhighlight>
 +
 +
Beispiel 2 (mit zurück zur Elternseite)
 +
<syntaxhighlight lang="php">
 +
$next = '';
 +
if($page->next->id){
 +
  $next = '
 +
  <a href="'.$page->next->url.'">
 +
    <i class="fa fa-angle-right"></i>
 +
  </a>
 +
';
 +
}
 +
 +
$prev = '';
 +
if($page->prev->id){
 +
  $prev = '
 +
  <a href="'.$page->prev->url.'" class="w-inline-block paginaton-but">
 +
    <i class="fa fa-angle-left"></i>
 +
  </a>';
 +
}
 +
 +
$pagination = '
 +
<div class="container pagination">
 +
  <div class="row">
 +
   
 +
    <div class="col col-md-4">
 +
      <div class="align-center">
 +
        '.$prev.'
 +
      </div>
 +
    </div>
 +
 +
    <div class="col col-md-4">
 +
      <div class="align-center">
 +
        <a href="'.$page->parent->url.'">
 +
          <i class="fa fa-th"></i>
 +
        </a>
 +
      </div>
 +
    </div>
 +
 +
    <div class="col col-md-4">
 +
      <div class="align-right center">
 +
        '.$next.'
 +
      </div>
 +
    </div>
 +
  </div>
 +
 +
</div>
 +
';
 +
 +
echo $pagination;
 +
</syntaxhighlight>
 +
 +
=== Zurück zur Elternseite ===
 +
<syntaxhighlight lang="php">
 +
<div class="back"><a href="'.$page->parent()->url.'">zurück</a></div>
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Zeile 212: Zeile 409:
 
$myMenu = wrap($myMenu,$wrapper);
 
$myMenu = wrap($myMenu,$wrapper);
 
echo $myMenu;
 
echo $myMenu;
 +
 
/*
 
/*
 
Navigation for ProcessWire using the Bootstrap 2.2.2 markup
 
Navigation for ProcessWire using the Bootstrap 2.2.2 markup
 
This menu was written by Soma based on work by NetCarver and a bit thrown in by Joss
 
This menu was written by Soma based on work by NetCarver and a bit thrown in by Joss
 
+
Bootstrap 3 update by Damienov, with multi level dropdown support fix
Navigation Bootstrap 3 update by Damienov, with multi level dropdown support fix
 
 
*/
 
*/
 
 
function renderChildrenOf($pa, $output = '', $level = 0)
 
function renderChildrenOf($pa, $output = '', $level = 0)
 
{
 
{
Zeile 263: Zeile 459:
 
?>
 
?>
 
</syntaxhighlight>
 
</syntaxhighlight>
== MarkupSimpleNavigation==
+
 
 +
== Modul: MarkupSimpleNavigation==
 
[[Processwire Modul - MarkupSimpleNavigation]]
 
[[Processwire Modul - MarkupSimpleNavigation]]
  
== Weitere Menüs ==
+
== Weitere Menübeispiele ==
=== Metamenü / Footer-Navigation ===
+
=== Flexible Funktion zum erzeugen von Tree oder Listen Navigationen ===
 +
//Todo fix depth (siehe MenuShifter Modul)
 +
* ul-Liste oder nur li
 +
* Rendertiefe einstellbar
 +
* Page Objekt von dem Kinder gerendert werden oder PageArray
 +
* Filter (Selector) für Kindobjekte.
 +
* Root voranstellen oder auch nicht (z.B. für Homepage)
 +
 
 +
<syntaxhighlight lang="php">
 +
/**
 +
* Rendert eine Navi. Kindseiten wenn eine Page übergeben wird.
 +
* Alle Seiten inkl. Kinder wenn ein PageArray übergeben wird.
 +
*
 +
*/
 +
function nav($items,$options = array()){
 +
static $depth = 0;
 +
$defaults = array(
 +
'ul' => true, // wrap in <ul> or not
 +
'class' => '', // class for ul
 +
'depth' => 1, // render depth
 +
'selector' => '', // filters child elements
 +
'prependRoot' => false // if you provide a Page (i.e. home), prepend as menu item
 +
);
 +
$options = array_merge($defaults, $options);
 +
$page = $items->wire('page'); // current page
 +
$class = $depth ? "nav-sub" : rtrim("nav $options[class]");
 +
$attr = rtrim("class='$class'");
 +
$out = $options['ul'] ? "<ul $attr>" : "";
 +
// if given a Page use children as the items and use Page as the header
 +
// if given a page array use each Page as the items
 +
if($items instanceof Page) {
 +
//$header = $items;
 +
if($options['prependRoot']) $out .= "<li class='root'> <a href='$items->url'>$items->title</a></li>";
 +
$items = $items->children($options['selector']);
 +
}
 +
if(!$items->count) return '';
 +
 
 +
foreach($items as $n => $item) {
 +
$isParent = $options['depth'] && $item->hasChildren && $depth < $options['depth'];
 +
$classes = array();
 +
 
 +
// determine additional classes
 +
if($item->id == $page->id) $classes[] = 'active';
 +
if($isParent) $classes[] = 'parent';
 +
 
 +
// open the list item
 +
$out .= count($classes) ? "<li class='" . implode(' ', $classes) . "'>" : "<li>";
 +
$out .= "<a href='$item->url'>$item->title</a>";
 +
// see if we are working with a nested list and go recursive if so
 +
if($isParent) {
 +
$depth++;
 +
$children = $item->children($options['selector']);
 +
$out .= nav($children, array(
 +
'depth' => $options['depth'],
 +
'selector' => $options['selector']
 +
));
 +
$depth--;
 +
}
 +
 
 +
// close the list item
 +
$out .= "</li>";
 +
}
 +
if($options['ul']) $out .= "</ul>";
 +
return $out;
 +
}
 +
</syntaxhighlight>
 +
 
 +
=== Standard Tree Navigation ===
 +
Für viele Zwecke ausreichend und leicht anpassbar, die klassische verschachtelte Liste.
 +
 
 +
 
 +
 
 +
=== Menüauswahl Hauptmenü / Metamenü / Footer-Navigation ===
 +
Beispiel 1
 +
Backend Feld menus anlegen Options:
 +
 
 +
1=Main Menu
 +
2=Meta Menu
 +
 
 +
topnav.inc
 +
<syntaxhighlight lang="php">
 +
$pa = $homepage->and($homepage->children("menus.id=1"));//only if main menu is checked
 +
$options = array('level' => '1', 'ulClass' => 'sf-menu', 'liClass' => '');
 +
echo "<div>".renderNavTreeType($pa, $maxDepth = 1, $fieldNames = '', $options)."</div>";
 +
</syntaxhighlight>
 +
 
 +
 
 +
'''Beispiel 2 (älter)'''
 +
 
 
Checkbox anlegen (footer_nav), und dann das Seitenarray etwa so modifizieren.
 
Checkbox anlegen (footer_nav), und dann das Seitenarray etwa so modifizieren.
 
<pre>
 
<pre>
Zeile 301: Zeile 586:
 
$navList = $col1.$col2;
 
$navList = $col1.$col2;
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
Mehrspaltige Navigationen lassen sich auch mit der slice Funktion erstellen:
 +
 +
<syntaxhighlight lang="php">
 +
$categories = $pages->get('/about/sites/categories/')->children();
 +
foreach($categories->slices(3) as $items) {
 +
  echo "<div class='uk-width-1-3'><ul>";
 +
  echo $items->each("<li><a href='{url}'>{title}</a>");
 +
  echo "</ul></div>";
 +
}
 +
</syntaxhighlight>
 +
 +
=== Pushy Menu ===
 +
<syntaxhighlight lang="php">
 +
/**
 +
* Given a group of pages, render a <ul> navigation tree
 +
*
 +
* This is here to demonstrate an example of a more intermediate level
 +
* shared function and usage is completely optional. This is very similar to
 +
* the renderNav() function above except that it can output more than one
 +
* level of navigation (recursively) and can include other fields in the output.
 +
* Assumes there is a field navigation_type to decide how a list item is
 +
* rendered
 +
*
 +
* @param array|PageArray $items
 +
* @param int $maxDepth How many levels of navigation below current should it go?
 +
* @param string $fieldNames Any extra field names to display (separate multiple fields with a space)
 +
* @param array $options extra options for classes configuration etc.
 +
* @return string
 +
*
 +
*/
 +
function renderPushyMenu($items, $maxDepth = 0, $fieldNames = '', $options = array('level' => 0, 'ulClass' => '', 'liClass' => '', 'aClass' => '') ) {
 +
 +
// if we were given a single Page rather than a group of them, we'll pretend they
 +
// gave us a group of them (a group/array of 1)
 +
if($items instanceof Page) $items = array($items);
 +
$out = '';
 +
  $c = 0;
 +
  $liClasses = array();
 +
  $ulClasses = array();
 +
$level = 0;
 +
$liClass = '';
 +
$ulClass = '';
 +
 +
if(!empty($options['level'])) $level = $options['level'];
 +
if(!empty($options['ulClass'])) {
 +
$ulClasses[] = $options['ulClass'];
 +
$ulClass = $options['ulClass'];
 +
}
 +
 +
if(!empty($options['liClass'])) {
 +
$liClasses[] = $options['liClass'];
 +
$liClass = $options['liClass'];
 +
}
 +
 +
// cycle through all the items
 +
foreach($items as $item) {
 +
    //$level = count($page->parents);
 +
// LI ITEM
 +
$classes = $liClasses;
 +
    //if($item->id == wire('page')->id) $classes[] = 'cur';
 +
if($item->hasChildren) {
 +
      // BUTTON instead of Link
 +
      $out .= '<li class="pushy-submenu"><button>'.$item->title.'</button>';
 +
}else{
 +
      $classes[] = 'level-'.$level;
 +
  $out .= '<li class="'.implode($classes,' ').'">';
 +
      unset($classes);
 +
 +
  // A ITEM
 +
  $navigation_type = $item->navigation_type->id;
 +
  $classes = $liClasses;
 +
  switch ( $navigation_type ) {
 +
  case 2: // do not link
 +
  $out .= '<span class="spacer">'.$item->title.'</span>';
 +
  break;
 +
  case 3: // link to subpage
 +
  if( $item->hasChildren() ){
 +
  $out .= '<a href="'.$item->child->url.'" class="ajax-link">'.$item->title.'</a>';
 +
  }else{
 +
  $out .= "<span class='spacer'>$item->title</span>";
 +
  }
 +
  break;
 +
  default:
 +
  $out .= '<a href="'.$item->url.'" class="ajax-link">'.$item->title.'</a>';
 +
  break;
 +
  }
 +
  unset($classes);
 +
}
 +
// if there are extra field names specified, render markup for each one in a <div>
 +
// having a class name the same as the field name
 +
if($fieldNames) foreach(explode(' ', $fieldNames) as $fieldName) {
 +
$value = $item->get($fieldName);
 +
if($value) $out .= " <div class='$fieldName'>$value</div>";
 +
}
 +
 +
// if the item has children and we're allowed to output tree navigation (maxDepth)
 +
// then call this same function again for the item's children
 +
if($item->hasChildren() && $maxDepth) {
 +
//if($class == 'nav') $class = 'nav nav-tree';
 +
$nextLevelOptions = array('level' => $level+1, 'ulClass' => '', 'liClass' => $liClass);
 +
$out .= renderNavTreeType($item->children, $maxDepth-1, $fieldNames, $nextLevelOptions);
 +
}
 +
 +
// close the list item
 +
$out .= "</li>\n";
 +
}
 +
 +
// if output was generated above, wrap it in a <ul>
 +
 +
if($out) $out = "\n".'<ul class="'.implode($ulClasses,' ').'">'."\n".$out.'</ul>'."\n";
 +
 +
// return the markup we generated above
 +
return $out;
 +
}
 +
 +
</syntaxhighlight>
 +
 +
== Do not link / link to subpage ==
 +
=== MarkupSimpleNavigation XTemplate + Redirect Beispiel ===
 +
 +
 +
https://github.com/s...default-options
 +
 +
'''Menü Platzhalter'''
 +
<syntaxhighlight lang="php">
 +
"xtemplate" => "folder|placeholder", // specify one or more templates
 +
"xitem_tpl" => "<span>{title}</span>", // default markup for page with this template
 +
"xitem_current_tpl" => "<span>{title}</span>"
 +
echo $nav->render(array(
 +
  'max_levels'=>2,
 +
  'selector'=>"limit=10",
 +
  'xtemplates' => 'placeholder|folder'
 +
));
 +
</syntaxhighlight>
 +
 +
'''Redirect Template'''
 +
 +
You could also have a template "redirect" with only a title and a page field (single page) to select any page you want to go.
 +
 +
Then in the code you should be able to write
 +
<syntaxhighlight lang="php">
 +
array('item_tpl' => '<a href="{redirect_page|url}">{title}</a>')
 +
</syntaxhighlight>
 +
So it would take the url of the referenced page in the page field if found, or if not it takes the url of the page itself. Assuming the page field is named "redirect_page".
 +
 +
=== In der Navi ===
 +
Zusätzliches Feld (Options) im Backend mit Namen navigation_type
 +
 +
Beispiel
 +
<syntaxhighlight lang="php">
 +
/**
 +
* Given a group of pages, render a <ul> navigation tree
 +
* If there is a field navigation_type the vals have following meaning
 +
* 1 = Normal
 +
* 2 = Do not link
 +
* 3 = Link to subpage
 +
*
 +
* @param array|PageArray $items
 +
* @param int $maxDepth How many levels of navigation below current should it go?
 +
* @param string $fieldNames Any extra field names to display (separate multiple fields with a space)
 +
* @param string $class CSS class name for containing <ul>
 +
* @return string
 +
*
 +
*/
 +
function renderNavTreeType($items, $maxDepth = 0, $fieldNames = '', $options = array('level' => 0, 'ulClass' => 'nav', 'liClass' => '', 'aClass' => '') ) {
 +
 +
// if we were given a single Page rather than a group of them, we'll pretend they
 +
// gave us a group of them (a group/array of 1)
 +
if($items instanceof Page) $items = array($items);
 +
 +
// $out is where we store the markup we are creating in this function
 +
$out = '';
 +
  $c = 0;
 +
  $liClasses = array();
 +
  $ulClasses = array();
 +
$level = 0;
 +
$liClass = '';
 +
$ulClass = '';
 +
 +
if(!empty($options['level'])) $level = $options['level'];
 +
if(!empty($options['ulClass'])) {
 +
$ulClasses[] = $options['ulClass'];
 +
$ulClass = $options['ulClass'];
 +
}
 +
 +
if(!empty($options['liClass'])) {
 +
$liClasses[] = $options['liClass'];
 +
$liClass = $options['liClass'];
 +
}
 +
 +
// cycle through all the items
 +
foreach($items as $item) {
 +
    //$level = count($page->parents);
 +
// LI ITEM
 +
$classes = $liClasses;
 +
    if($item->id == wire('page')->id) $classes[] = 'cur';
 +
if($item->hasChildren) $classes[] = 'has_children';
 +
    $classes[] = 'level-'.$level;
 +
$out .= '<li class="'.implode($classes,' ').'">';
 +
    unset($classes);
 +
 +
// markup for the link
 +
$navigation_type = $item->navigation_type->id;
 +
$classes = $liClasses;
 +
switch ( $navigation_type ) {
 +
case 2: // do not link
 +
$out .= '<span class="spacer">'.$item->title.'</span>';
 +
break;
 +
case 3: // link to subpage
 +
if( $item->hasChildren() ){
 +
$out .= '<a href="'.$item->child->url.'" class="ajax-link">'.$item->title.'</a>';
 +
}else{
 +
$out .= "<span class='spacer'>$item->title</span>";
 +
}
 +
break;
 +
default:
 +
$out .= '<a href="'.$item->url.'" class="ajax-link">'.$item->title.'</a>';
 +
break;
 +
}
 +
unset($classes);
 +
// if there are extra field names specified, render markup for each one in a <div>
 +
// having a class name the same as the field name
 +
if($fieldNames) foreach(explode(' ', $fieldNames) as $fieldName) {
 +
$value = $item->get($fieldName);
 +
if($value) $out .= " <div class='$fieldName'>$value</div>";
 +
}
 +
 +
// if the item has children and we're allowed to output tree navigation (maxDepth)
 +
// then call this same function again for the item's children
 +
if($item->hasChildren() && $maxDepth) {
 +
//if($class == 'nav') $class = 'nav nav-tree';
 +
$nextLevelOptions = array('level' => $level+1, 'ulClass' => '', 'liClass' => $liClass);
 +
$out .= renderNavTreeType($item->children, $maxDepth-1, $fieldNames, $nextLevelOptions);
 +
}
 +
 +
// close the list item
 +
$out .= "</li>\n";
 +
}
 +
 +
// if output was generated above, wrap it in a <ul>
 +
 +
if($out) $out = "\n".'<ul class="'.implode($ulClasses,' ').'">'."\n".$out.'</ul>'."\n";
 +
 +
// return the markup we generated above
 +
return $out;
 +
}
 +
</syntaxhighlight>
 +
 +
=== Redirect über das Template ===
 +
Sinnvoll wenn die URL direkt aufgerufen wird:
 +
 +
$session->redirect($page->redirect_page->url);
 +
or how about "redirect-to-firstchild".
 +
 +
$session->redirect($page->children->first()->url);
 +
 +
== Beispiele für Funktionen (z.B. in _func.php)==
 +
=== Externe Links finden ===
 +
<syntaxhighlight lang="php">
 +
public function isExternalLink($url) {
 +
foreach($this->config->httpHosts as $hostname) {
 +
// If the target host is one of our own hostnames,
 +
// this link is not external.
 +
if(preg_match("~^https?://{$hostname}~i", $url)) return false;
 +
}
 +
 +
// Otherwise, all http(s) links are definitely external
 +
// and get redirected.
 +
if(preg_match('~^https?://~i', $url)) return true;
 +
 +
// No match, then we have a relative url (internal) or some other
 +
// scheme (e.g. mailto) that we don't redirect.
 +
return false;
 +
}
 +
</syntaxhighlight>
 +
'''Beispiele für Funktionen die Navigationen erzeugen. '''
 +
=== One Level ===
 +
==== Original ProcessWire Demo Beispiel ====
 +
 +
 +
 +
=== Nested List ausgehend von einer Seite (meistens Homepage) ===
 +
<syntaxhighlight lang="php">
 +
<?php namespace ProcessWire;
 +
 +
/**
 +
  * Given a group of pages, render a ONE LEVEL NAVBAR
 +
  *
 +
  * @param array|PageArray $items
 +
  * @return string
 +
  *
 +
  */
 +
function renderNavMain($pa,$pageId){
 +
  if($pa instanceof Page) $pa = array($pa);
 +
  $out = '<nav class="menu menu--ferdinand"><ul class="nav navbar-nav menu__list">';
 +
  foreach($pa as $item) {
 +
    if($item->id == $pageId) {
 +
      $out .= "<li class=\"menu__item menu__item--current cur\">";
 +
    } else {
 +
      $out .= "<li class=\"menu__item\">";
 +
    }
 +
    // if template isotope-parent add first isotope-child name as hash
 +
    if($item->template->name == 'isotope-parent'){
 +
      $out .= '<a class="menu__link" href="'.$item->url.'#'.$item->child->name.'">'.$item->title.'</a></li>';
 +
    }else $out .= '<a class="menu__link" href="'.$item->url.'">'.$item->title.'</a></li>';
 +
  }
 +
    $out .= "</ul></nav>";
 +
    return $out;
 +
}
 +
 +
/**
 +
  * Given a group of pages render a standard ISOTOP MARKUP
 +
  *
 +
  * @param array|PageArray $items
 +
  * @return string
 +
  *
 +
  */
 +
function renderNavIsotope($pa){
 +
  if($pa instanceof Page) $pa = array($pa);
 +
  $out = '<ul class="submenu">';
 +
  foreach($pa as $item){
 +
    $out .= '<li><a href="#'.$item->name.'" class="isotope-link">'.$item->title.'</a></li>';
 +
  }
 +
  $out .= "</ul>";
 +
  return $out;
 +
}
 +
 +
 +
/**
 +
* Given a group of pages, render a simple <ul> navigation
 +
*
 +
* This is here to demonstrate an example of a simple shared function.
 +
* Usage is completely optional.
 +
*
 +
* @param PageArray $items
 +
* @return string
 +
*
 +
*/
 +
function renderNav(PageArray $items) {
 +
 +
// $out is where we store the markup we are creating in this function
 +
$out = '';
 +
 +
// cycle through all the items
 +
foreach($items as $item) {
 +
 +
// render markup for each navigation item as an <li>
 +
if($item->id == wire('page')->id) {
 +
// if current item is the same as the page being viewed, add a "current" class to it
 +
$out .= "<li class='current'>";
 +
} else {
 +
// otherwise just a regular list item
 +
$out .= "<li>";
 +
}
 +
 +
// markup for the link
 +
$out .= "<a href='$item->url'>$item->title</a> ";
 +
 +
// if the item has summary text, include that too
 +
if($item->summary) $out .= "<div class='summary'>$item->summary</div>";
 +
 +
// close the list item
 +
$out .= "</li>";
 +
}
 +
 +
// if output was generated above, wrap it in a <ul>
 +
if($out) $out = "<ul class='nav'>$out</ul>\n";
 +
 +
// return the markup we generated above
 +
return $out;
 +
}
 +
 +
 +
 +
/**
 +
* Given a group of pages, render a <ul> navigation tree
 +
*
 +
* This is here to demonstrate an example of a more intermediate level
 +
* shared function and usage is completely optional. This is very similar to
 +
* the renderNav() function above except that it can output more than one
 +
* level of navigation (recursively) and can include other fields in the output.
 +
*
 +
* @param array|PageArray $items
 +
* @param int $maxDepth How many levels of navigation below current should it go?
 +
* @param string $fieldNames Any extra field names to display (separate multiple fields with a space)
 +
* @param string $class CSS class name for containing <ul>
 +
* @return string
 +
*
 +
*/
 +
function renderNavTree($items, $maxDepth = 0, $fieldNames = '', $class = 'nav') {
 +
 +
// if we were given a single Page rather than a group of them, we'll pretend they
 +
// gave us a group of them (a group/array of 1)
 +
if($items instanceof Page) $items = array($items);
 +
 +
// $out is where we store the markup we are creating in this function
 +
$out = '';
 +
 +
// cycle through all the items
 +
foreach($items as $item) {
 +
 +
// markup for the list item...
 +
// if current item is the same as the page being viewed, add a "current" class to it
 +
$out .= $item->id == wire('page')->id ? "<li class='current'>" : "<li>";
 +
 +
// markup for the link
 +
$out .= "<a href='$item->url'>$item->title</a>";
 +
 +
// if there are extra field names specified, render markup for each one in a <div>
 +
// having a class name the same as the field name
 +
if($fieldNames) foreach(explode(' ', $fieldNames) as $fieldName) {
 +
$value = $item->get($fieldName);
 +
if($value) $out .= " <div class='$fieldName'>$value</div>";
 +
}
 +
 +
// if the item has children and we're allowed to output tree navigation (maxDepth)
 +
// then call this same function again for the item's children
 +
if($item->hasChildren() && $maxDepth) {
 +
if($class == 'nav') $class = 'nav nav-tree';
 +
$out .= renderNavTree($item->children, $maxDepth-1, $fieldNames, $class);
 +
}
 +
 +
// close the list item
 +
$out .= "</li>";
 +
}
 +
 +
// if output was generated above, wrap it in a <ul>
 +
if($out) $out = "<ul class='$class'>$out</ul>\n";
 +
 +
// return the markup we generated above
 +
return $out;
 +
}
 +
 +
</syntaxhighlight>
 +
 +
== Komplette Beispiele ==
 +
[[ProcessWire - Navigation Beispiele]]

Aktuelle Version vom 7. März 2025, 12:58 Uhr

TODO Seite aufräumen[Bearbeiten]

Siehe auch[Bearbeiten]

Processwire Module: MarkupSimpleNavigation automatisch Navigation aus Seitenbaum erstellen
Aligator (ProcessWire) - automatische Navigation, gut wenn manipuliert werden muss.
Menu Builder (ProcessWire) - Menüs im Backend erstellen (Wordpress like)

Navigation in Pagewire - Einführung[Bearbeiten]

Navigationstypen allgemein[Bearbeiten]

Es gibt verschiedene Typen von Navigationen. In Processwire hat man ein Pages Objekt, indem auch Zugriff auf Kind- und Elternseiten möglich sind. Es bildet also immer die Sitestruktur ab. Daher übergibt man an die unten aufgeführten Funktionen entweder die Homepage oder die aktuelle Seite.

Unter dem Aspekt auf welcher Seite man sich befindet kann man unterscheiden zwischen:

  • absolute Navigation normalerweise ausgehend von der Rootseite. diese ist dann auf allen Seiten gleich.
    • z.B. alle Seiten des ersten Levels stehen in der Hauptnavigation egal auf welcher Seite ich im Moment bin
    • z.B. verschachtelte Liste mit 2 oder mehr Leveln für Dropdown Navigationen wie Superfish, Megamenüs (mit zusätzlichen Infos...) oder Bootstrap Navigationen.
    • Sitemap
  • Navigation relativ zur Seite Diese kann sich von Seite zu Seite unterscheiden.
    • Alle Seiten der aktuellen Ebene (oft kombiniert mit Breadcrumb / Hier-bin-ich) )
    • Hauptebene und aktueller Level
    • Alle Ebenen bis zur aktuellen Seite + deren Unterseiten falls vorhanden.

In letzten Fall könnte man auch Varianten bauen in denen eine Verschachtelte Liste erzeugt wird aber nur bestimmte Teile absolut Positioniert angezeigt werden und andere versteckt werden. Manchmal möchte man bestimmte Level aber auch an anderer Position zeigen (z.B. Sidebar) In der Praxis hat man in der Regel

  • Mindestens eine Hauptnavigation mit allen Seiten der 1. Ebene oder eine Hauptnavigation mit mehreren Ebenen für Dropdown Navigationen, mobile Navigation oder auch Sitemapartige Navigationen für den Footer (oft mit kleinen Beschreibungen).
  • Eine Metanavigation mit Service Seiten wie Kontakt, Impressum etc. oft ist diese im Footer.

Unterschiede zwischen Verstecken, Veröffentlichen, Sperren[Bearbeiten]

In Processwire sind diese Begriffe mit Userrechten verknüpft. Eine unveröffentlichte Seite kann also durchaus im Frontend aufgerufen werden (es sei denn man regelt das anders.) Vielmehr geht es darum das man User Rollen so gestalten kann, dass man z.B. einem User nur erlaubt unveröffentlichte Seiten zu editieren.

Denoch gibt es auch ein paar weitere Unterschiede.

Gesperrt -> Man kann die Seite nicht zum Editieren aufrufen. Über die Url kann Sie aufgerufen werden.

Unpublished -> Die Seite kann sobald sie gespeichert ist auch aufgerufen werden, WENN der User berechtigt ist. Nicht für Guest User (der normale Viewer)

TODO checken ob die Tabelle so für nicht angemeldete User stimmt.

Im Menü ($pages->find) Über URL erreichbar($pages->get) Ausgabe im Frontend
Unpublished / Unveröffentlicht Nein Nur User mit passenden Rechten. Gäste -> leere Seite
Hidden / Versteckt Nein Ja Ja - leere Seite (keine Feldausgabe)
Locked / Gesperrt Ja Ja Ja
Trash Nein Nein

Seiten auf unveröffentlicht stellen[Bearbeiten]

https://processwire.com/talk/topic/29-how-to-unpublish-a-page-without-deleting-it/

Was soll man tun wenn man eine Seite tatsächlich nicht mehr anzeigen will, sie aber noch nicht wegwerfen will? Ryan schlägt folgendes vor:

  • Mülleimer
  • Remove Guest Role in Template

Basics[Bearbeiten]

Minimal Navigation Bar[Bearbeiten]

Aus dem Standard Template

<?php
$homepage = $pages->get("/");
$navigation = $homepage->and($homepage->children)->implode(" / ", "<a href='{url}'>{title}</a>"); 
?>
<p id="topnav">
  <?= $navigation ?>
</p>

Basic Navigation[Bearbeiten]

<?php
  // get the homepage object
  $homepage = $pages->get("/");
  // get PageArray of homepage object and child page objects
  $navItems = $homepage->and($homepage->children);
?>
Now you have a PageArray with the required items, you can iterate over them one at a time, and print the title of the page and the link to the page itself and wrap the whole thing in your list tag.

<ul class="nav">

<?php
  // get the homepage object
  $homePage = $pages->get("/");
  // get PageArray of homepage object and child page objects
  $navItems = $homePage->and($homePage->children);
  // or if you don't want the home link
  // $navItems = $homePage->children;
  // iterate over the $navItems PageArray
  foreach ($navItems as $navItem):
?>

  <li class="nav-item">
    <a class="nav-link" href="<?php echo $navItem->url; ?>"><?php echo $navItem->title; ?></a>
  </li>

  <?php endforeach; ?>

</ul>

Basic mit active Class[Bearbeiten]

<ul class="nav">

<?php
  // get the homepage object
  $homePage = $pages->get("/");
  // get PageArray of homepage object and child page objects
  $navItems = $homePage->and($homePage->children);
  // or if you don't want the home link
  // $navItems = $homePage->children;
  // iterate over the $navItems PageArray
  foreach ($navItems as $navItem):

// if the id of the page currently being
// iterated equals the id of the current page
$activeClass = ($navItem->id == $page->id) ? " active" : "";
?>

  <li class="nav-item">
    <a class="nav-link<?php echo $activeClass; ?>" href="<?php echo $navItem->url; ?>"><?php echo $navItem->title; ?></a>
  </li>

  <?php endforeach; ?>

</ul>

Child Menu[Bearbeiten]

<ul class="sub-menu">

<?php
  // get children of the parent of the current page
  $childPages = $page->parent->children;

  // iterate over the $navItems PageArray
  foreach ($childPages as $childPage):

  // if the id of the page currently being
  // iterated equals the id of the current page
  $activeClass = ($navItem->id == $page->id) ? " active" : "";
?>

  <li class="nav-item">
    <a class="nav-link<?php echo $activeClass; ?>" href="<?php echo $childPage->url; ?>"><?php echo $childPage->title; ?></a>
  </li>

  <?php endforeach; ?>

</ul>

Page Level[Bearbeiten]

In which level in page tree we are?

$level = count($page->parents);

Parent, active parent[Bearbeiten]

$isParent = $item->hasChildren;
$isActiveParent = $item->child('id='.$page->id)->id; // Seite ist in Rootline wenn sie ein aktives Kind hat

Link to Subpage und Platzhalter (Spacer)[Bearbeiten]

Kann man gut für Superfish Menüs etc. benutzen. Bildet das Verhalten von Shortcuts und Spacern aus TYPO3 nach.

Anpassung der renderNavTree() Funktion von Ryan Cramer. Options Field Installieren und als globales Feld "navigation_type" mit den Optionen

1=normal|Normal
2=doNotLink|Do not link
3=linkToFirstChild|Link to first childpage

konfigurieren. Dann Funktion etwa so anpassen:

...
// cycle through all the items
	foreach($items as $item) {

		// markup for the list item...
		// if current item is the same as the page being viewed, add a "current" class to it
		$out .= $item->id == wire('page')->id ? "<li class='current'>" : "<li>";

		// markup for the link
		$navigation_type = $item->navigation_type->id;
		switch ( $navigation_type ) {
			case 2: // do not link
				$out .= "<span class='spacer'>$item->title</span>";
				break;
			case 3: // link to subpage
				if( $item->hasChildren() ){
					$out .= '<a href="'.$item->child->url.'">'.$item->title.'</a>';
				}else{
					$out .= "<span class='spacer'>$item->title</span>";
				}
				break;
			default:
				$out .= "<a href='$item->url'>$item->title</a>";
				break;
		}
...

Redirect (301)[Bearbeiten]

Redirect zu erster Unterseite[Bearbeiten]

https://processwire.com/talk/topic/15-how-do-i-create-a-page-that-redirects-to-its-first-child/

Field redirects_to_first_child erstellen und im Template einfügen.

<?php 
  if($page->numChildren && $page->redirects_to_first_child) 
  $session->redirect($page->child()->url); 
?>

Erzeugt 301 Weiterleitung

Anderer Ansatz wäre evtl. den Link bei der Menügenerierung direkt zu generieren. finde ich persönlich besser siehe Link to subpage und Platzhalter Beispiel. Allerdings sollte man dann vielleicht die Seite trotzdem per 301 Weiterleiten, falls die URL mal direkt aufgerufen wird oder bei Google gelistet ist.

Redirect zu anderer Seite in der Navigation[Bearbeiten]

https://processwire.com/talk/topic/762-howto-menu-item-that-links-to-another-page/

1. Create a new field and call it 'redirect_url' or something like that, and use the 'URL' fieldtype.

2. Add that field to your template where you'd want to use it, or create a new template just for the purpose, like a template named 'redirect'.

3. Edit the page that you want to be a symlink and populate the 'redirect_url' field with the URL you want it to redirect to.

4. In your nav-generation code that links to the pages, do something like this:

<?php
$url = $subpage->get("redirect_url|url"); // use redirect_url if there, otherwise use url
echo "<a href='$url'>{$subpage->title}</a>";

5. You might also want to add this to your template that has the 'redirect_url' field: just in case there's anything linking to it directly. That way it'll send people to the right place either way:

<?php
if($page->redirect_url) $session->redirect($page->redirect_url); 

Breadcrumb[Bearbeiten]

<!-- breadcrumbs -->
<div class='breadcrumbs'>
<?php 
	// breadcrumbs are the current page's parents
	foreach($page->parents() as $item) {
		echo "<span><a href='$item->url'>$item->title</a></span> "; 
	}
	// optionally output the current page as the last item
	echo "<span>$page->title</span> "; 
?>
</div>

One Level Navigation Bar[Bearbeiten]

ProcessWire - One Level Navigation

Nächste Seite / Next Page Navigation[Bearbeiten]

Beispiel 1

if($page->next->id){
  $next = '
    <div class="next">
      <i>Next:</i>&nbsp;
      <a class="ajax-link" name="'.$page->next->title.'" href="'. $page->next->url .'">
        '. $page->next->title .'<span class="fa fa-arrow-right"><span>
      </a>
    </div>';
}

Beispiel 2 (mit zurück zur Elternseite)

$next = '';
if($page->next->id){
  $next = '
  <a href="'.$page->next->url.'">
    <i class="fa fa-angle-right"></i>
  </a>
';
}

$prev = '';
if($page->prev->id){
  $prev = '
  <a href="'.$page->prev->url.'" class="w-inline-block paginaton-but">
    <i class="fa fa-angle-left"></i>
  </a>';
}

$pagination = '
<div class="container pagination">
  <div class="row">
    
    <div class="col col-md-4">
      <div class="align-center">
        '.$prev.'
      </div>
    </div>

    <div class="col col-md-4">
      <div class="align-center">
        <a href="'.$page->parent->url.'">
          <i class="fa fa-th"></i>
        </a>
      </div>
    </div>

    <div class="col col-md-4">
      <div class="align-right center">
        '.$next.'
      </div>
    </div>
  </div>

</div>
';

echo $pagination;

Zurück zur Elternseite[Bearbeiten]

<div class="back"><a href="'.$page->parent()->url.'">zurück</a></div>

Kindseiten mit $page->children[Bearbeiten]

<?=$page->children?>

Output

5723,4958,5937

Beispiel

<ul>
<?php
foreach($page->children as $child)
  echo "<li><a href='{$child->url}'>{$child->title}</a></li>";
?>
</ul>

Ergebnis:

<ul>

<li><a href='/about/contact/'>Contact Us</a></li>
<li><a href='/about/press/'>Press Releases</a></li>
<li><a href='/about/staff/'>Our Staff</a></li>

</ul>

Children Tree[Bearbeiten]

function listChildrenTree($children, $current, $w) {

echo "<ul>";

foreach($children as $page) {

	$class = '';
	if($page === $current || $current->parents->slice(1)->has($page) ) {
		$class = "class='on' style='font-weight:bold'";
	}

	$rootid = $w->pages->get("/")->id;

	echo "<li><a href='{$page->url}' $class>";
	if($page->id == $rootid) echo "<img src='" . $w->config->urls->templates . "styles/images/home.png' width='24' height='28' alt='' />";
	echo "{$page->title}</a> ";

	if($page->numChildren && $page->id != $rootid) listChildrenTree($page->children, $current, $w);

	echo "</li>";
}
echo "</ul>";
}

$children = $pages->get("/")->children();
$children->prepend($pages->get("/"));

listChildrenTree($children, $page, $wire);

Bootstrap Navigation[Bearbeiten]

<?php namespace ProcessWire;
// Markup to use wicht navigation_type field (normal=1, no-link=2,subpage=3)
?>

<?php

// bundle up the first level pages and prepend the root home page
$homepage = $pages->get(1);
$pa = $homepage->children;
$pa = $pa->prepend($homepage);

// Set the ball rolling...
$myMenu = renderChildrenOf($pa);
$wrapper = '
<nav class="navbar navbar-default">
  <div class="container-fluid">
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse-1" aria-expanded="false">
        <span class="sr-only">Menü</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
    </div>
    <div class="collapse navbar-collapse" id="navbar-collapse-1">
      |
    </div>
  </div>
</div>';
$myMenu = wrap($myMenu,$wrapper);
echo $myMenu;

/*
Navigation for ProcessWire using the Bootstrap 2.2.2 markup
This menu was written by Soma based on work by NetCarver and a bit thrown in by Joss
Bootstrap 3 update by Damienov, with multi level dropdown support fix
*/
function renderChildrenOf($pa, $output = '', $level = 0)
{
    $output = '';
    $level++;

    foreach ($pa as $child) {
        $atoggle = '';
        $class = '';

        if ($child->numChildren && count($child->parents) == 1) {
            $class .= 'dropdown';
            $atoggle .= ' class="dropdown-toggle" data-toggle="dropdown"';
        } else if ($child->numChildren && count($child->parents) > 1 ) {
            $class .= 'dropdown-submenu';
            $atoggle .= ' class="dropdown-toggle"';
        } else if ($child->numChildren && $child->id != 1) {
            $class .= 'dropdown-menu';
        }

        // Makes the current page and it's top level parent add an active class
        $class .= ($child === wire("page") || $child === wire("page")->rootParent) ? " active" : '';
        $class = strlen($class) ? " class='" . trim($class) . "'" : '';

        if ($child->numChildren && count($child->parents) == 1) {
            // Add Caret if have children
            $output .= "<li$class><a href='$child->url'$atoggle>$child->title <b class='caret'></b></a>";
        } else if ($child->numChildren && count($child->parents) > 1) {
            $output .= "<li$class><a tabindex='-1' href='$child->url'$atoggle>$child->title</a>";
        } else {
            $output .= "<li$class><a href='$child->url'$atoggle>$child->title</a>";
        }

        // If this child is itself a parent and not the root page, then render it's children in their own menu too...
        if ($child->numChildren && $child->id != 1) {
            $output .= renderChildrenOf($child->children, $output, $level);
        }
        $output .= '</li>';
    }
    $outerclass = ($level == 1) ? "nav navbar-nav" : 'dropdown-menu';
    return "<ul class='$outerclass'>$output</ul>";
}

?>

Modul: MarkupSimpleNavigation[Bearbeiten]

Processwire Modul - MarkupSimpleNavigation

Weitere Menübeispiele[Bearbeiten]

Flexible Funktion zum erzeugen von Tree oder Listen Navigationen[Bearbeiten]

//Todo fix depth (siehe MenuShifter Modul)

  • ul-Liste oder nur li
  • Rendertiefe einstellbar
  • Page Objekt von dem Kinder gerendert werden oder PageArray
  • Filter (Selector) für Kindobjekte.
  • Root voranstellen oder auch nicht (z.B. für Homepage)
/**
 * Rendert eine Navi. Kindseiten wenn eine Page übergeben wird. 
 * Alle Seiten inkl. Kinder wenn ein PageArray übergeben wird.
 * 
 */
function nav($items,$options = array()){
	static $depth = 0;
	$defaults = array(
		'ul' => true, // wrap in <ul> or not
		'class' => '', // class for ul
		'depth' => 1, // render depth
		'selector' => '', // filters child elements
		'prependRoot' => false // if you provide a Page (i.e. home), prepend as menu item
	);
	$options = array_merge($defaults, $options);
	$page = $items->wire('page'); // current page
	$class = $depth ? "nav-sub" : rtrim("nav $options[class]");
	$attr = rtrim("class='$class'");
	$out = $options['ul'] ? "<ul $attr>" : "";
	// if given a Page use children as the items and use Page as the header
	// if given a page array use each Page as the items
	if($items instanceof Page) {
		//$header = $items;
		if($options['prependRoot']) $out .= "<li class='root'> <a href='$items->url'>$items->title</a></li>";
		$items = $items->children($options['selector']);
	}
	if(!$items->count) return '';

	foreach($items as $n => $item) {
		$isParent = $options['depth'] && $item->hasChildren && $depth < $options['depth'];
		$classes = array();

		// determine additional classes
		if($item->id == $page->id) $classes[] = 'active';
		if($isParent) $classes[] = 'parent';

		// open the list item
		$out .= count($classes) ? "<li class='" . implode(' ', $classes) . "'>" : "<li>";
		$out .= "<a href='$item->url'>$item->title</a>";
		// see if we are working with a nested list and go recursive if so
		if($isParent) {
			$depth++;
			$children = $item->children($options['selector']);
			$out .= nav($children, array(
				'depth' => $options['depth'],
				'selector' => $options['selector']
			));
			$depth--;
		}

		// close the list item
		$out .= "</li>";
	}
	if($options['ul']) $out .= "</ul>";
	return $out;
}

Standard Tree Navigation[Bearbeiten]

Für viele Zwecke ausreichend und leicht anpassbar, die klassische verschachtelte Liste.


Menüauswahl Hauptmenü / Metamenü / Footer-Navigation[Bearbeiten]

Beispiel 1 Backend Feld menus anlegen Options:

1=Main Menu
2=Meta Menu 

topnav.inc

$pa = $homepage->and($homepage->children("menus.id=1"));//only if main menu is checked
$options = array('level' => '1', 'ulClass' => 'sf-menu', 'liClass' => '');
echo "<div>".renderNavTreeType($pa, $maxDepth = 1, $fieldNames = '', $options)."</div>";


Beispiel 2 (älter)

Checkbox anlegen (footer_nav), und dann das Seitenarray etwa so modifizieren.

$footer_nav = $pages->find("parent=1, footer_checkbox=1");
$main_nav = $pages->find("parent=1, footer_checkbox!=1");

Zweispaltige Navigation aus Kindseiten[Bearbeiten]

Verbesserungsvorschlag: Anstatt if lieber zwei for Schleifen -> bessere Performance

// Childrens
$n = count($page->children);
$m = ceil($n/2);
$c = 0;

// NAVIGATION & SLIDER Items
$listItem = '';
$navList = '';
$col1 = '<ul class="nav-list col1">';
$col2 = '<ul class="nav-list col2">';
foreach ($page->children as $item) {
	if($item->id == $page->rootParent->id) {
		$listItem = '<li class="current">';
	} else {
		$listItem = '<li>';
	}
	$listItem .= '<a class="ajax-link" href="'.$item->url.'">'.$item->title.'</a></li>';
	($c < $m) ? $col1 .= $listItem : $col2 .= $listItem;
	$c++;
}
$col1 .= '</ul>';
$col1 .= '</ul>';
$navList = $col1.$col2;

Mehrspaltige Navigationen lassen sich auch mit der slice Funktion erstellen:

$categories = $pages->get('/about/sites/categories/')->children();
foreach($categories->slices(3) as $items) {
  echo "<div class='uk-width-1-3'><ul>";
  echo $items->each("<li><a href='{url}'>{title}</a>");
  echo "</ul></div>";
}

Pushy Menu[Bearbeiten]

/**
 * Given a group of pages, render a <ul> navigation tree
 *
 * This is here to demonstrate an example of a more intermediate level
 * shared function and usage is completely optional. This is very similar to
 * the renderNav() function above except that it can output more than one
 * level of navigation (recursively) and can include other fields in the output.
 * Assumes there is a field navigation_type to decide how a list item is
 * rendered
 *
 * @param array|PageArray $items
 * @param int $maxDepth How many levels of navigation below current should it go?
 * @param string $fieldNames Any extra field names to display (separate multiple fields with a space)
 * @param array $options extra options for classes configuration etc.
 * @return string
 *
 */
function renderPushyMenu($items, $maxDepth = 0, $fieldNames = '', $options = array('level' => 0, 'ulClass' => '', 'liClass' => '', 'aClass' => '') ) {

	// if we were given a single Page rather than a group of them, we'll pretend they
	// gave us a group of them (a group/array of 1)
	if($items instanceof Page) $items = array($items);
	$out = '';
  $c = 0;
  $liClasses = array();
  $ulClasses = array();
	$level = 0;
	$liClass = '';
	$ulClass = '';

	if(!empty($options['level'])) $level = $options['level'];
	if(!empty($options['ulClass'])) {
		$ulClasses[] = $options['ulClass'];
		$ulClass = $options['ulClass'];
	}

	if(!empty($options['liClass'])) {
		$liClasses[] = $options['liClass'];
		$liClass = $options['liClass'];
	}

	// cycle through all the items
	foreach($items as $item) {
    //$level = count($page->parents);
		// LI ITEM
		$classes = $liClasses;
    //if($item->id == wire('page')->id) $classes[] = 'cur';
		if($item->hasChildren) {
      // BUTTON instead of Link
      $out .= '<li class="pushy-submenu"><button>'.$item->title.'</button>';
		}else{
      $classes[] = 'level-'.$level;
  		$out .= '<li class="'.implode($classes,' ').'">';
      unset($classes);

  		// A ITEM
  		$navigation_type = $item->navigation_type->id;
  		$classes = $liClasses;
  		switch ( $navigation_type ) {
  			case 2: // do not link
  				$out .= '<span class="spacer">'.$item->title.'</span>';
  				break;
  			case 3: // link to subpage
  				if( $item->hasChildren() ){
  					$out .= '<a href="'.$item->child->url.'" class="ajax-link">'.$item->title.'</a>';
  				}else{
  					$out .= "<span class='spacer'>$item->title</span>";
  				}
  				break;
  			default:
  				$out .= '<a href="'.$item->url.'" class="ajax-link">'.$item->title.'</a>';
  				break;
  		}
  		unset($classes);
		}
		// if there are extra field names specified, render markup for each one in a <div>
		// having a class name the same as the field name
		if($fieldNames) foreach(explode(' ', $fieldNames) as $fieldName) {
			$value = $item->get($fieldName);
			if($value) $out .= " <div class='$fieldName'>$value</div>";
		}

		// if the item has children and we're allowed to output tree navigation (maxDepth)
		// then call this same function again for the item's children
		if($item->hasChildren() && $maxDepth) {
			//if($class == 'nav') $class = 'nav nav-tree';
			$nextLevelOptions = array('level' => $level+1, 'ulClass' => '', 'liClass' => $liClass);
			$out .= renderNavTreeType($item->children, $maxDepth-1, $fieldNames, $nextLevelOptions);
		}

		// close the list item
		$out .= "</li>\n";
	}

	// if output was generated above, wrap it in a <ul>

	if($out) $out = "\n".'<ul class="'.implode($ulClasses,' ').'">'."\n".$out.'</ul>'."\n";

	// return the markup we generated above
	return $out;
}

Do not link / link to subpage[Bearbeiten]

MarkupSimpleNavigation XTemplate + Redirect Beispiel[Bearbeiten]

https://github.com/s...default-options

Menü Platzhalter

"xtemplate" => "folder|placeholder", // specify one or more templates
"xitem_tpl" => "<span>{title}</span>", // default markup for page with this template
"xitem_current_tpl" => "<span>{title}</span>"
echo $nav->render(array(
   'max_levels'=>2,
   'selector'=>"limit=10",
   'xtemplates' => 'placeholder|folder'
));

Redirect Template

You could also have a template "redirect" with only a title and a page field (single page) to select any page you want to go.

Then in the code you should be able to write

array('item_tpl' => '<a href="{redirect_page|url}">{title}</a>')

So it would take the url of the referenced page in the page field if found, or if not it takes the url of the page itself. Assuming the page field is named "redirect_page".

In der Navi[Bearbeiten]

Zusätzliches Feld (Options) im Backend mit Namen navigation_type

Beispiel

/**
 * Given a group of pages, render a <ul> navigation tree
 * If there is a field navigation_type the vals have following meaning
 * 1 = Normal
 * 2 = Do not link
 * 3 = Link to subpage
 *
 * @param array|PageArray $items
 * @param int $maxDepth How many levels of navigation below current should it go?
 * @param string $fieldNames Any extra field names to display (separate multiple fields with a space)
 * @param string $class CSS class name for containing <ul>
 * @return string
 *
 */
function renderNavTreeType($items, $maxDepth = 0, $fieldNames = '', $options = array('level' => 0, 'ulClass' => 'nav', 'liClass' => '', 'aClass' => '') ) {

	// if we were given a single Page rather than a group of them, we'll pretend they
	// gave us a group of them (a group/array of 1)
	if($items instanceof Page) $items = array($items);

	// $out is where we store the markup we are creating in this function
	$out = '';
  $c = 0;
  $liClasses = array();
  $ulClasses = array();
	$level = 0;
	$liClass = '';
	$ulClass = '';

	if(!empty($options['level'])) $level = $options['level'];
	if(!empty($options['ulClass'])) {
		$ulClasses[] = $options['ulClass'];
		$ulClass = $options['ulClass'];
	}

	if(!empty($options['liClass'])) {
		$liClasses[] = $options['liClass'];
		$liClass = $options['liClass'];
	}

	// cycle through all the items
	foreach($items as $item) {
    //$level = count($page->parents);
		// LI ITEM
		$classes = $liClasses;
    if($item->id == wire('page')->id) $classes[] = 'cur';
		if($item->hasChildren) $classes[] = 'has_children';
    $classes[] = 'level-'.$level;
		$out .= '<li class="'.implode($classes,' ').'">';
    unset($classes);

		// markup for the link
		$navigation_type = $item->navigation_type->id;
		$classes = $liClasses;
		switch ( $navigation_type ) {
			case 2: // do not link
				$out .= '<span class="spacer">'.$item->title.'</span>';
				break;
			case 3: // link to subpage
				if( $item->hasChildren() ){
					$out .= '<a href="'.$item->child->url.'" class="ajax-link">'.$item->title.'</a>';
				}else{
					$out .= "<span class='spacer'>$item->title</span>";
				}
				break;
			default:
				$out .= '<a href="'.$item->url.'" class="ajax-link">'.$item->title.'</a>';
				break;
		}
		unset($classes);
		// if there are extra field names specified, render markup for each one in a <div>
		// having a class name the same as the field name
		if($fieldNames) foreach(explode(' ', $fieldNames) as $fieldName) {
			$value = $item->get($fieldName);
			if($value) $out .= " <div class='$fieldName'>$value</div>";
		}

		// if the item has children and we're allowed to output tree navigation (maxDepth)
		// then call this same function again for the item's children
		if($item->hasChildren() && $maxDepth) {
			//if($class == 'nav') $class = 'nav nav-tree';
			$nextLevelOptions = array('level' => $level+1, 'ulClass' => '', 'liClass' => $liClass);
			$out .= renderNavTreeType($item->children, $maxDepth-1, $fieldNames, $nextLevelOptions);
		}

		// close the list item
		$out .= "</li>\n";
	}

	// if output was generated above, wrap it in a <ul>

	if($out) $out = "\n".'<ul class="'.implode($ulClasses,' ').'">'."\n".$out.'</ul>'."\n";

	// return the markup we generated above
	return $out;
}

Redirect über das Template[Bearbeiten]

Sinnvoll wenn die URL direkt aufgerufen wird:

$session->redirect($page->redirect_page->url);

or how about "redirect-to-firstchild".

$session->redirect($page->children->first()->url);

Beispiele für Funktionen (z.B. in _func.php)[Bearbeiten]

Externe Links finden[Bearbeiten]

public function isExternalLink($url) {
		foreach($this->config->httpHosts as $hostname) {
			// If the target host is one of our own hostnames,
			// this link is not external.
			if(preg_match("~^https?://{$hostname}~i", $url)) return false;
		}
		
		// Otherwise, all http(s) links are definitely external
		// and get redirected.
		if(preg_match('~^https?://~i', $url)) return true;
		
		// No match, then we have a relative url (internal) or some other
		// scheme (e.g. mailto) that we don't redirect.
		return false;
	}

Beispiele für Funktionen die Navigationen erzeugen.

One Level[Bearbeiten]

Original ProcessWire Demo Beispiel[Bearbeiten]

Nested List ausgehend von einer Seite (meistens Homepage)[Bearbeiten]

<?php namespace ProcessWire;

 /**
  * Given a group of pages, render a ONE LEVEL NAVBAR
  *
  * @param array|PageArray $items
  * @return string
  *
  */
 function renderNavMain($pa,$pageId){
   if($pa instanceof Page) $pa = array($pa);
   $out = '<nav class="menu menu--ferdinand"><ul class="nav navbar-nav menu__list">';
   foreach($pa as $item) {
     if($item->id == $pageId) {
       $out .= "<li class=\"menu__item menu__item--current cur\">";
     } else {
       $out .= "<li class=\"menu__item\">";
     }
     // if template isotope-parent add first isotope-child name as hash
     if($item->template->name == 'isotope-parent'){
       $out .= '<a class="menu__link" href="'.$item->url.'#'.$item->child->name.'">'.$item->title.'</a></li>';
     }else $out .= '<a class="menu__link" href="'.$item->url.'">'.$item->title.'</a></li>';
   }
     $out .= "</ul></nav>";
     return $out;
 }

 /**
  * Given a group of pages render a standard ISOTOP MARKUP
  *
  * @param array|PageArray $items
  * @return string
  *
  */
 function renderNavIsotope($pa){
   if($pa instanceof Page) $pa = array($pa);
   $out = '<ul class="submenu">';
   foreach($pa as $item){
     $out .= '<li><a href="#'.$item->name.'" class="isotope-link">'.$item->title.'</a></li>';
   }
   $out .= "</ul>";
   return $out;
 }


/**
 * Given a group of pages, render a simple <ul> navigation
 *
 * This is here to demonstrate an example of a simple shared function.
 * Usage is completely optional.
 *
 * @param PageArray $items
 * @return string
 *
 */
function renderNav(PageArray $items) {

	// $out is where we store the markup we are creating in this function
	$out = '';

	// cycle through all the items
	foreach($items as $item) {

		// render markup for each navigation item as an <li>
		if($item->id == wire('page')->id) {
			// if current item is the same as the page being viewed, add a "current" class to it
			$out .= "<li class='current'>";
		} else {
			// otherwise just a regular list item
			$out .= "<li>";
		}

		// markup for the link
		$out .= "<a href='$item->url'>$item->title</a> ";

		// if the item has summary text, include that too
		if($item->summary) $out .= "<div class='summary'>$item->summary</div>";

		// close the list item
		$out .= "</li>";
	}

	// if output was generated above, wrap it in a <ul>
	if($out) $out = "<ul class='nav'>$out</ul>\n";

	// return the markup we generated above
	return $out;
}



/**
 * Given a group of pages, render a <ul> navigation tree
 *
 * This is here to demonstrate an example of a more intermediate level
 * shared function and usage is completely optional. This is very similar to
 * the renderNav() function above except that it can output more than one
 * level of navigation (recursively) and can include other fields in the output.
 *
 * @param array|PageArray $items
 * @param int $maxDepth How many levels of navigation below current should it go?
 * @param string $fieldNames Any extra field names to display (separate multiple fields with a space)
 * @param string $class CSS class name for containing <ul>
 * @return string
 *
 */
function renderNavTree($items, $maxDepth = 0, $fieldNames = '', $class = 'nav') {

	// if we were given a single Page rather than a group of them, we'll pretend they
	// gave us a group of them (a group/array of 1)
	if($items instanceof Page) $items = array($items);

	// $out is where we store the markup we are creating in this function
	$out = '';

	// cycle through all the items
	foreach($items as $item) {

		// markup for the list item...
		// if current item is the same as the page being viewed, add a "current" class to it
		$out .= $item->id == wire('page')->id ? "<li class='current'>" : "<li>";

		// markup for the link
		$out .= "<a href='$item->url'>$item->title</a>";

		// if there are extra field names specified, render markup for each one in a <div>
		// having a class name the same as the field name
		if($fieldNames) foreach(explode(' ', $fieldNames) as $fieldName) {
			$value = $item->get($fieldName);
			if($value) $out .= " <div class='$fieldName'>$value</div>";
		}

		// if the item has children and we're allowed to output tree navigation (maxDepth)
		// then call this same function again for the item's children
		if($item->hasChildren() && $maxDepth) {
			if($class == 'nav') $class = 'nav nav-tree';
			$out .= renderNavTree($item->children, $maxDepth-1, $fieldNames, $class);
		}

		// close the list item
		$out .= "</li>";
	}

	// if output was generated above, wrap it in a <ul>
	if($out) $out = "<ul class='$class'>$out</ul>\n";

	// return the markup we generated above
	return $out;
}

Komplette Beispiele[Bearbeiten]

ProcessWire - Navigation Beispiele