Es sind Smarty - Kenntnisse dringend und zwingend erforderlich wie auch logisches Denkvermögen, ansonsten werden Sie scheitern !
Man muss sich über die gelieferte Datenstruktur von Powermenu oder Pmenu im klaren sein.
Unterschiede zwischen PowerMenu und Pmenu
- Powermenu erzeugt per Default auch Daten für andere Dinge wie Breadcrumbs, Prev-Next - Pmenu erzeugt lediglich Menüdaten.
- Powermenu verarbeitet Informationen bis zur dritten Hierarchie, Pmenu bis zur vierten.
Bei beiden Plugins wäre allerdings eine weitere Hochrüstung innerhalb weniger Sekunden durchzuführen.
- Powermenu erzeugt zudem eine zusätzliche Struktur mit SECTION und ENDSECTION Pmenu nicht.
Ab PowerSite Download 6 stellt das Plugin Pmenu auch die Daten für Breadcrumbs und Prev-Next zur Verfügung.
Darüber hinaus ist die interne Arbeitsweise anders, da Powermenu mit einer Datenbank arbeitet und Pmenu nicht.
{foreach from=$menu item=section_item}
{if $section_item=='SECTION'}
{elseif $section_item=='ENDSECTION'}
{else}
{repeat string='.' times=$section_item.level}
|{$section_item.menu_text}
|{$root_url}/index.php?{$query_var}={$section_item.content_alias}{linefeed}
{/if}
{/foreach}
Was man vorher wissen muss !
Das wichtigste ist - was erwartet PHPLayers als Datenbasis.
Da ist PHPLayers in der Basisnutzung für alle Menüarten verblüffend einfach.
Level - dargestellt durch Punkte und gefolgt vom Menütext, danach der Link - alles getrennt durch das Zeichen | und jede Zeile durch ein Linefeed separiert ( \n)).
Zum Template selbst
Geringe Anforderungen erfordern einen geringen Aufwand.
Daten aus Powermenu und Pmenu werden immer in Array-Form zur Verfügung gestellt, deshalb erfolgt der Durchlauf auch immer mit einer Schleife.
Das Einzelmitglied eines Arrays taucht hier in der Variable section_item auf.
Da wir SECTION und ENDSECTION nicht benötigen fallen die in den Abfragen durch, d.h. keinerlei Aktion.
Dann aber wird der Punkt ausgegeben und zwar über das Plugin repeat.
Repeat gibt hier so viele Punkte aus , wie der Level des Menüeintrages hoch ist.
Nun erfolgt das Zeichen | als Trennmittel, dann der Menütext, dann wieder der Trenner und dann die URL des Links.
{$root_url} und {$query_var} sind Smarty-Variable die im Standard bereits immer unter Powermenu vordefiniert sind. {linefeed} ist ein Miniplugin das lediglich "\n" ausgibt.
Fertig ist das ganze Template.
Es ist der Demo von PowerCMS zu PHPLayers in Aktion zu sehen - für alle drei Varianten ist es das gleiche Template .
{assign var='img_link' value='<img src="images/cms/arrow-right.gif" class="img_link" alt="Linkpfeil" />'}
{assign var='img_link_a' value='<img src="images/cms/arrow-right-active.gif" class="img_link" alt="Linkpfeil" />'}
{assign var='last' value=0}
<ul>
{foreach from=$menu item=section_item}
{if ($currentpage.firsthierarchy eq $section_item.firsthierarchy and $section_item.level eq 2)
or ($currentpage.firsthierarchy eq $section_item.firsthierarchy and $currentpage.secondhierarchy eq $section_item.secondhierarchy and $section_item.level eq 3)
or ($currentpage.firsthierarchy eq $section_item.firsthierarchy and $currentpage.secondhierarchy eq $section_item.secondhierarchy and $currentpage.thirdhierarchy eq $section_item.thirdhierarchy and $section_item.level eq 4)
or $section_item.level eq 1}
{if $section_item.level >$last.level}
{repeat string="<ul>" times=$section_item.level-$last.level}
{elseif $section_item.level<$last.level}
{repeat string="</li></ul>" times=$last.level-$section_item.level}
{$smarty.capture.closing}
{else}
{$smarty.capture.closing}
{/if}
{assign var='last' value=$section_item}
{if $section_item.current == true and $section_item.type eq 'content' }
<li><p class="current">{$img_link_a}{$section_item.menu_text}</p>
{elseif $section_item.type == 'sectionheader'}
<li><strong>{$section_item.menu_text}</strong>
{elseif $section_item.type == 'link'}
<li><a {if $section_item.secondhierarchy neq false}class="secondlevel"{/if}
href="{$section_item.titel}">{$img_link}{$section_item.menu_text}</a>
{elseif $section_item.type == 'separator'}
<li class="separator"><hr />
{else}
<li><a {if $section_item.secondhierarchy neq false}class="secondlevel"{/if}
href="{$root_url}/index.php?{$query_var}={$section_item.content_alias}&sprache={$sprache}">
{$img_link}{$section_item.menu_text}</a>
{/if}
{capture name=closing}</li>{/capture}
{/if}
{/foreach}
</li></ul>
Das ist das Template simple_collapse3 für Pmenu wie wir es selbst verwenden für vier Hierarchiestufen, es ist bis auf die vierte Stufe auch für PowerMenu einsetzbar.
Es erzeugt eine valide geschachtelte Liste - mit ein wenig CSS man daraus ein wunderbares CSS - Menü gestalten - horizontal aber auch vertikal.
Wer das versteht kann alle Menüs bauen, die er haben will.
Am Anfang stehen ein paar Zuweisungen an Smarty bezüglich kleiner Link - Bilder, die wollen wir nicht immer komplett ausschreiben.
Es wird über Smarty eine Variable last mit einem Anfangswert von 0 zugewiesen, damit wir für Vergleichszwecke einen definiefrten Wert haben.
Dann erfolgt die Eröffnung der Liste ul.
Es wird die Schleife gestartet.
Das Ziel
Bevor wir nun das Template ausweiden muss die Frage geklrärt sein, was das Ziel ist.
- Es sollen alle Menüpunkte angezeigt werden, die Level 1 aufweisen.
- Es sollen alle Menüpunkte angezeigt werden, deren Hierarchieanteile identisch bis zum aktuell gewählten Link sind.
Damit hätten wir das System aufklappbare Menüanteile.
Das hört sich nicht so kompliziert an, aber wie macht man es ?
Filtern durch Abfragen
Die Hauptarbeit wird gleich nach dem Schleifenstart erledigt.
Da wir hier vier Hierarchiestufen abfragen müssen, fällt die Abfrage etwas länger aus.
Die Abfrage, welche alle Level 1 Position durchlässt steht am Schluss der IF Abfrage.
or $section_item.level eq 1
Damit wird erreicht, das alle Level 1 Positionen durchgelassen werden.
Die Werte der aktuellen Seite stehen in der Variable currentpage, das ist der erste Vergleichswert.
Der nachfolgende Abfrageteil der ODER Auswertung wiederholt sich um jeweils eine Hierarchistufe.
$currentpage.firsthierarchy eq $section_item.firsthierarchy and $section_item.level eq 2
Damit werden aber exakt die Menüanteile heraus geholt, die man benötigt.
Und - die werden dann durch die nachfolgenden Stufen geschickt.
Html Formalitäten
Daran muss natürlich auch gedacht werden.
Ein wesentlicher Teil findet in dem folgenden Code - Abschnitt statt.
{if $section_item.level >$last.level}
{repeat string="<ul>" times=$section_item.level-$last.level}
{elseif $section_item.level<$last.level}
{repeat string="</li></ul>" times=$last.level-$section_item.level}
{$smarty.capture.closing}
{else}
{$smarty.capture.closing}
{/if}
Wenn der Level größer ist als der letzte Level dann wird ein ul Teil ausgegeben und zwar so häufig wie sich der aktuelle Level vom letzten unterscheidet.
Dafür wird wieder das kleine Hilfsplugin repeat eingesetzt.
Ist der aktuelle Level kleiner als der letzte Level, dann muss die Liste abgeschlossen werden /ul , auch da setzen wir wieder das Hilfsplugin repeat ein.
Jetzt wird es ein wenig kompliziert, denn wir setzen die Smarty - Funktion capture ein, die wir hier an der Stelle schliessen und damit capture zwingen, die gesammelten Werke auszugeben.
Das muss sein, weil wir nicht nur /ul setzen müssen, sondern auch die Anzhal von /li .
Ist der Level gleich dem letzten Level, müssen wir diesen Listeneintrag abschliessen ( /li).
Auch dazu schliessen wir capture.
In dem Zusammenhang muss man sich das Ende des Filters ansehen, da hier capture gestartet wird.
{capture name=closing}</li>{/capture}
{/if}
{/foreach}
Gleich nach diesen Formalitäten wird der Variable last der aktuelle Schleifenwert zugewiesen, den wir immer wieder zu Vergleichszwecken benötigen.
{assign var='last' value=$section_item}
Danach erfolgt nur noch eine Auswertung nach den Inhaltstypen und die Bildung der Detailausgabe.
Das war es auch schon - das Menütemplate ist fertig.
Auf dem ersten Blick sieht es kompliziert aus, ist aber programmtechnisch eine ganz einfache Sache.
Wichtig ist, das das Ziel genau definiert wird.
Sehen Sie auch die Notwendigkeiten die HTML erfordert.
Das eben gezeigte Menütemplate für verschachtelte Listen erfordert weit mehr Kenntnisse auf CSS - Ebene als Kenntnisse die man zum Verständnis von Smarty benötigt - aber es war ja auch nur ein Beispiel.
Mit Powermenu und Pmenu läßt sich buchstäblich alles machen, was wie ein Menü aussieht - auch in Zusammenarbeit mit Javasrcipt - Menüs.
Listenmenüs sind von Haus aus kompliziert, aber man kann nach dem gleichen Schema und einfacher gut aussehende Menüs z.B. mit normalen p-Absätzen machen.
Da entfallen dann auch "undurchschaubare" Aktionen mit Smarty capture und ähnliches.
Der Filtermechanismus ist dabei immer sehr ähnlich.
Betrachten Sie doch einmal das Menü hier - das ist ein einfaches Menü mit p-Absätzen aufgebaut.
{assign var='img_link_1' value='<img src="images/cms/arrow-right.gif" class="img_link_1" alt="Linkpfeil" />'}
{assign var='img_link_2' value='<img src="images/cms/arrow-right.gif" class="img_link_2" alt="Linkpfeil" />'}
{assign var='img_link_3' value='<img src="images/cms/arrow-right.gif" class="img_link_3" alt="Linkpfeil" />'}
{assign var='img_link_4' value='<img src="images/cms/arrow-right.gif" class="img_link_4" alt="Linkpfeil" />'}
{assign var='img_link_a1' value='<img src="images/cms/arrow-right-active.gif" class="img_link_1" alt="Linkpfeil" />'}
{assign var='img_link_a2' value='<img src="images/cms/arrow-right-active.gif" class="img_link_2" alt="Linkpfeil" />'}
{assign var='img_link_a3' value='<img src="images/cms/arrow-right-active.gif" class="img_link_3" alt="Linkpfeil" />'}
{assign var='img_link_a4' value='<img src="images/cms/arrow-right-active.gif" class="img_link_4" alt="Linkpfeil" />'}
{assign var='img_link_e' value='<img src="images/cms/extern_link.gif" class="img_link_e" alt="Linkpfeil" />'}
{assign var='blank' value='<img src="images/cms/blank.jpg" class="img_link_e" alt="Blank" />'}
{foreach from=$menu item=section_item}
{if ($currentpage.firsthierarchy eq $section_item.firsthierarchy and $section_item.level eq 2)
or ($currentpage.firsthierarchy eq $section_item.firsthierarchy and $currentpage.secondhierarchy eq $section_item.secondhierarchy and $section_item.level eq 3) or ($currentpage.firsthierarchy eq $section_item.firsthierarchy and $currentpage.secondhierarchy eq $section_item.secondhierarchy and $currentpage.thirdhierarchy eq $section_item.thirdhierarchy and $section_item.level eq 4)
or ($currentpage.firsthierarchy eq $section_item.firsthierarchy and $currentpage.secondhierarchy eq $section_item.secondhierarchy and $currentpage.thirdhierarchy eq $section_item.thirdhierarchy and $currentpage.fourthhierarchy eq $section_item.fourthhierarchy and $section_item.level eq 5) or $section_item.level eq 1 }
{if $section_item.current == true and $section_item.type eq 'content' }
{if $section_item.level eq 1}
<p class="current">{$img_link_a1}{$section_item.menu_text}</p>
{elseif $section_item.level eq 2}
<p class="current">{$img_link_a2}{$section_item.menu_text}</p>
{elseif $section_item.level eq 3}
<p class="current">{$img_link_a3}{$section_item.menu_text}</p>
{elseif $section_item.level eq 4}
<p class="current">{$img_link_a4}{$section_item.menu_text}</p>
{else}
<p class="current">{$img_link_a4}{$section_item.menu_text}</p>
{/if}
{elseif $section_item.type == 'sectionheader'}
{if $section_item.level eq 1}
{$blank}<a href="#">{$section_item.menu_text}</a>
{elseif $section_item.level eq 2}
{$blank}<a href="#">{$section_item.menu_text}</a>
{elseif $section_item.level eq 3}
{$blank}<a href="#">{$section_item.menu_text}</a>
{elseif $section_item.level eq 4}
{$blank}<a href="#">{$section_item.menu_text}</a>
{else}
{$blank}<a href="#">{$section_item.menu_text}</a>
{/if}
{elseif $section_item.type == 'link'}
<a class="nav_1" href="{$section_item.titel}">{$img_link_1} {$section_item.menu_text}{$img_link_e}</a>
{elseif $section_item.type == 'separator'}
<p class="separator"><hr />
{else}
{if $section_item.level eq 1}
<a class="nav_1" href="{$root_url}/{$section_item.content_alias}.html">
{elseif $section_item.level eq 2}
<a class="nav" href="{$root_url}/{$section_item.content_alias}.html">
{elseif $section_item.level eq 3}
<a class="nav" href="{$root_url}/{$section_item.content_alias}.html">
{elseif $section_item.level eq 4}
<a class="nav" href="{$root_url}/{$section_item.content_alias}.html">
{else}
<a class="nav" href="{$root_url}/{$section_item.content_alias}.html">
{/if}
{if $section_item.level eq 1}
{$img_link_1}
{elseif $section_item.level eq 2}
{$img_link_2}
{elseif $section_item.level eq 3}
{$img_link_3}
{elseif $section_item.level eq 4}
{$img_link_4}
{else}
{$img_link_4}
{/if}
{$section_item.menu_text}</a>
{/if}
{/if}
{/foreach}
Auch wenn das Listing lang ist - das Menü selbst ist sehr einfach.
Die Funktion selbst kann man hier in der Wiki genau nachvollziehen.
Am Templatenanfang werden aus Gründen der bequemeren Verwendung einige Imagelinks an Smarty übergeben, die irgendwann im Template selbst Verwendung finden.
Ansonsten erfolgt die übliche Abfrage nach der Hierarchiezugehörigkeit und der Typen und dann natürlich die Linkbildung.
Die optische Gestaltung erfolgt wir immer mit CSS.
Hier wierd ein geteiltes Menü gezeigt, das die Hauptpunkte horizontal anzeigt und nur die jeweils zu einem Hauptpunkt gehörenden Unterpunkte vertikal anbietet.
Bei der vertikalen Einheit werden nur dann weitere Unterpunkte angezeigt, wenn die betreffende Seite aktiv ist.
Der horizontale Teil:
{foreach from=$menu item=section_item}
{if $section_item.level eq 1}
{if $section_item=='SECTION'}
{elseif $section_item=='ENDSECTION'}
{else}
{if $section_item.current == true}
<img src="images/cms/1.png" width="1" height="1" alt="" /><a href="{$root_url}/index.php?{$query_var}={$section_item.content_alias}" class="Aktiv" title="{$section_item.content_name}" cesskey}"{/if}{if $section_item.tabindex != ''} tabindex="{$section_item.tabindex}"{/if}{if $section_item.titleattribute != ''} title="{$section_item.titleattribute}"{/if}{if $section_item.target != ''} target="{$section_item.target}"{/if}>{$section_item.menu_text}</a>
{else}
{if $currentpage.firsthierarchy eq $section_item.firsthierarchy and $section_item.parent eq 1}
<img src="images/cms/1.png" width="1" height="1" alt="" /><a href="{$root_url}/index.php?{$query_var}={$section_item.content_alias}" class="Aktiv" title="{$section_item.content_name}" {if $section_item.accesskey != ''} accesskey="{$section_item.accesskey}"{/if}{if $section_item.tabindex != ''} tabindex="{$section_item.tabindex}"{/if}{if $section_item.titleattribute != ''} title="{$section_item.titleattribute}"{/if}{if $section_item.target != ''} target="{$section_item.target}"{/if}>{$section_item.menu_text}</a>
{else}
<img src="images/cms/1.png"width="1" height="1" alt="" /><a href="{$root_url}/index.php?{$query_var}={$section_item.content_alias}" class="genNavigationEbene1" title="{$section_item.content_name}" {if $section_item.accesskey != ''} accesskey="{$section_item.accesskey}"{/if}{if $section_item.tabindex != ''} tabindex="{$section_item.tabindex}"{/if}{if $section_item.titleattribute != ''} title="{$section_item.titleattribute}"{/if}{if $section_item.target != ''} target="{$section_item.target}"{/if}>{$section_item.menu_text}</a>
{/if}
{/if}
{/if}
{/if}
{/foreach}
<img src="images/cms/1.png" width="1" height="1" alt="" /><a href="http://wiki.powercms.org" class="genNavigationEbene1" title="Wiki">Wiki</a>
<img src="images/cms/1.png" width="1" height="1" alt="" /><a href="http://forum.powercms.org" class="genNavigationEbene1" title="Zum Forum">Forum</a>
<img src="images/cms/1.png" width="1" height="1" alt="" /><a href="http://demo.powercms.org" class="genNavigationEbene1" title="Zur Demoversion">Demo</a>
Der vertikale Teil:
{counter start=-1 assign="level2"}
{counter}
{foreach from=$menu item=section_item}
{if $currentpage.firsthierarchy eq $section_item.firsthierarchy and $section_item.level > 1}
{if $section_item=='SECTION'}
{elseif $section_item=='ENDSECTION'}
{else}
{counter}
{if $section_item.type eq 'content'}
{if $section_item.current == true}
<img src="images/cms/1.png" alt="" /><a href="{$root_url}/index.php?{$query_var}={$section_item.content_alias}" class="topAktiv" title="{$section_item.content_name}"{if $section_item.accesskey != ''} accesskey="{$section_item.accesskey}"{/if}{if $section_item.tabindex != ''} tabindex="{$section_item.tabindex}"{/if}{if $section_item.titleattribute != ''} title="{$section_item.titleattribute}"{/if}{if $section_item.target != ''} target="{$section_item.target}"{/if}>{$section_item.menu_text}</a>
{else}
{if $currentpage.secondhierarchy eq false and $section_item.level < 3}
<img src="images/cms/1.png" alt="" /><a href="{$root_url}/index.php?{$query_var}={$section_item.content_alias}" class="genNavigationEbene1" title="{$section_item.content_name}"{if $section_item.accesskey != ''} accesskey="{$section_item.accesskey}"{/if}{if $section_item.tabindex != ''} tabindex="{$section_item.tabindex}"{/if}{if $section_item.titleattribute != ''} title="{$section_item.titleattribute}"{/if}{if $section_item.target != ''} target="{$section_item.target}"{/if}>{$section_item.menu_text}</a>
{elseif $currentpage.secondhierarchy and $currentpage.secondhierarchy eq $section_item.secondhierarchy and $currentpage.firsthierarchy eq $section_item.firsthierarchy or $section_item.level eq 2}
<img src="images/cms/1.png" alt="" /><a href="{$root_url}/index.php?{$query_var}={$section_item.content_alias}" class="genNavigationEbene1" title="{$section_item.content_name}"{if $section_item.accesskey != ''} accesskey="{$section_item.accesskey}"{/if}{if $section_item.tabindex != ''} tabindex="{$section_item.tabindex}"{/if}{if $section_item.titleattribute != ''} title="{$section_item.titleattribute}"{/if}{if $section_item.target != ''} target="{$section_item.target}"{/if}>{$section_item.menu_text}</a>
{/if}
{/if}
{elseif $section_item.type == 'link'}
<img src="images/cms/1.png" alt="" /><a href ="{$section_item.url}" {if $section_item.target <>''}target="{$section_item.target}"{/if} title="{$section_item.content_name}" >{$section_item.menu_text}</a>
{/if}
{/if}
{/if}
{/foreach}
{if $level2 eq 0}
<p>Schon mal im Forum gestöbert ?</p>
{/if}
Das Template ist zwar lang aber leicht zu verstehen.
In der horizontalen Variante werden nur Level 1 Positionen verarbeitet.
Demzufolge werden in der vertikalen Version nur Positionen mit Level > 1 erfasst und es werden da die Hierarchiepositionen ausgewertet, damit man nur eine Anzeige der Unterpunkte zur aktiven Seite erhält.
In der horizontalen Variante werden zusätzlich ein paar Positionen manuell angehängt, dafür gibt es in der vertikalen Version eine Zählerauswertung mit der ermittelt wird, ob überhaupt Unterpunkte vorhanden sind.
Hier wurde für den Fall nur ein kleiner Text eingesetzt, man könnte aber auch den freien Platz für ganz andere Dinge nutzen.
Dieses Menü ist übrigens bei PowerCMS.org im Einsatz.
Mit Powermenu und Pmenu lassen sich alle Arten von Menüs erstellen.
Dabei spielt es keine Rolle ob es sich um einfache Auflistungen, Listenmenüs oder geteilte Menüs handelt.
Wer will kann problemlos auch die bekannten aufklappbaren horizontalen oder vertikalen CSS Menüs erstellen.
Ebenso ist die Verwendung von Javascriptmenüs machbar.
Bei denen werden die Menüinhalte oftmals als Javascript gehalten.
Wer oder was hindert uns daran ein Javascript über ein Smartytemplate schreiben zu lassen ?
Niemand , denn wer sagt , das man mit Smarty nur HTML erzeugen kann ?
Das immer wiederkehrende Problem ist tatsächlich, das es wegen der Aufbröselung der Hierarchie längere Templates gibt und diese wegen der Menge kompliziert erscheinen.
Beschränkt man sich in der Betrachtung mal nur auf eine einzige Hierachie, dann erkennt man sofort wie einfach das in Wirklichkeit ist.
Bei manchem Anwender fällt dann der Groschen.
Die verwendeten Smartyanweisungen sind einfachster Natur und beschränken sich auf eine Schleife und normalen if - Abfragen.
Logisches Denkvermögen allerdings ist gefragt, denn Denkfehler machen sich erbarmungslos in Nichtfunktion bemerkbar.
Aber - einfache if - Abfragen , das kann jeder hin bekommen, bedeutet eine solche doch nichts weiter als, wenn das ist mach das.