EF77D1707F3B455596FF5F03692E44A6
  • Thomas Pollinger
  • 21.03.2019
  • DE

How-To: Navigationseinträge mehrfach verwenden

Der Navigation-Manager des Management Servers hat derzeit eine Einschränkung, welche es einem unmöglich macht Navigations-Einträge oder Teilstrukturen mehrfach im Navigationsbaum zu verwenden. Jetzt könnte man sich fragen, warum sollte man dies auch tun wollen. Gerade Themen wie SEO mit den s.g. Duplicate Content und weitere ähnliche Themen könnten ja ein Problem werden. Doch es geht nicht um die Verdopplung der Seiten, sondern nur die mehrfache Verlinkung der selben Seite im Navigationsbaum, an unterschiedlichen sinnvollen Stellen. Doch wie sollte das nun möglich sein, wenn der Navigations-Manager des Management Servers damit nicht klar kommt? Es gibt eine Lösung, welche zwar ein s.g. Workaround ist, jedoch einem genau dieses zuvor beschriebene Verhalten ermöglicht.

Als erstes möchte ich jedoch kurz an einem Bild die Aufgabenstellung erläutern und dannach eine Schritt für Schritt Anleitung aufzeigen.
 

Anforderung

Die Anforderung lautet, dass folgende Navigationspunkte an anderen Stellen in der Navigationsstruktur nochmals verwendet werden sollen:

  • Dokumente unter Fachbereich A
  • Fachliteratur unter Fachbereich B
  • Mitteilungen unter Neues im Unternehmen

Da man die Seiten derzeit nicht mehrfach innerhalb der Navigation verlinken kann, muss man zu einem Workaround greifen.
 

Workaround - Navigation-Collector

Schritt 1 - Erweiterung der Masterpage

Die Masterpage (in diesem Fall alle, welche innerhalb der Navigation verwendet werden) müssen um ein Anchor-Element erweitert werden:

welches folgende Einstellungen bekommt:

Es ist jedoch nicht notwendig dieses neue Strukturelement innerhalb der Templates einzusetzen. Denn es wird nur über den Navigations-Manager ausgelesen.

Quelltext der Masterpage (Beispiel):

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Management Server</title>
    <style>
        * {
             font-family: Arial, Helvetica, sans-serif;
             font-size: 12px;
        }
    </style>
  </head>
  <body>
    <ul><%!! Navigation:OutputArea(String:NavigationStructure) !!%></ul>
  </body>
</html><!IoRangeNoRedDotMode><!IoRangeRedDotMode><!-- <%listNavigation%> --><!/IoRangeRedDotMode><!/IoRangeNoRedDotMode>

 

Schritt 2 - Neue Navigations-Manager Content-Klasse

Als nächstes sind zwei weitere Content-Klasse für den Navigations-Manager nötig. Die Syntax für dieses Beispiel sieht wie folgt aus:

Content-Klasse: Navigation - JumpLevel

<navigation:nextlevel>

Content-Klasse: Navigation - Level 1-10

<%!! Store:Set(linkedContents,Context:CurrentIndex.Page.Elements.GetElement(Str:anchorNavigationCollector).GetLinkedContents()) !!%>
<%!! Store:Set(navigationAreaName,String:NavigationCollectorDepth) !!%>
<%!! Store:Set(navigationAreaNameLevel,Store:Get(navigationAreaName).Insert(Int:24,Context:CurrentDepth.ToString())) !!%>

<reddot:cms>
    <if>
        <query valuea="Store:Get(linkedContents).Count" operator="!=" valueb="Int:0">
            <foreach itemname="linkedPage" object="Store:Get(linkedContents)"></foreach> <!-- Workaround for "Get the GUID from linked page at anchor" -->
            <htmltext>
                <li><b><%!! Context:CurrentIndex.Page.Headline !!%></b><br>
                    <sup>(<%!! Store:Get(linkedPage).Id !!%> / <%!! Store:Get(linkedContents).Count !!%>)</sup>
                    <ul>
                        <%!! Navigation:OutputArea(Store:Get(navigationAreaNameLevel), Bool:False, Store:Get(linkedPage).Id) !!%>
                    </ul>
                </li></htmltext>
        </query>
        <query type="else">
            <htmltext>
                <li><b><%!! Context:CurrentIndex.Page.Headline !!%></b><br>
                <sup>(<%!! Context:CurrentIndex.Page.Id!!%> / <%!! Store:Get(linkedContents).Count !!%>)</sup>
            </htmltext>
            <if>
                <query valuea="Context:CurrentIndex.HasChildren()" operator="==" valueb="Bool:True">
                    <htmltext><ul><navigation:nextlevel></ul></htmltext>
                </query>
            </if>
            <htmltext></li></htmltext>
        </query>
    </if>
</reddot:cms>

 

Schritt 3 - Neue Navigationsbereiche

Nachdem man die Content-Klassen für den Navigations-Manager angelegt hat, müssen nun mehrere neue Navigationsbereiche eingerichtet werden. Die Anzahl der Navigationsbereiche richtet sich nach der Navigations-Tiefe, welche für den Navigation-Collector genutzt werden sollen:

In diesem Beispiel werden die Navigationsebenen 1, 2 und 3 berücksichtigt. Die erste Ebene (0) wird übersprungen.
 

Schritt 4 - Die Navigationsbereiche verknüpfen oder verweisen

Nun sucht man sich die entsprechenden Seiten raus und legt sich diese in Ablage. In unserem Beispiel die Seiten aus der o.g. Liste. Danach wird jede Seite entsprechend verwiesen oder verknpüft. Mit diesem Workaround ist beides möglich:

Wenn man nun eine Seitenvorschau ausführt oder im SmartEdit sich die z.B. die Homepage anschaut, bekommt man dieses Ergebnis:

Es wird wie gewünscht die verwiesenen oder verknüpften Teilbäume des Navigationbaums, in anderen Bereichen der Navigationstruktur angezeigt. Ohne negative Einflüsse auf den Navigations-Manager, werden die Teilbäume dargestellt. Mit diesem Workaround kann man sich die Headline, Id und die URL zu den mehrfach verwendeten Seiten abholen. Mit weiteren Aufwand lässt sich auch weitere Inhalte abholen, jedoch damit wird auch das Rendering der Navigation aufwändiger und dauert länger.

Man muss jedoch beachten, dass der Navigation-Collecotor (in dieser Lösung) die nachfolgende reguläre Navigation ignoriert. Und diese durch die verwiesene bzw. verknüpfte Navigation über den Anchor darstellt. Man kann sich auch einen Mischbetrieb vorstellen, jedoch macht dies dann die Pflege im Projekt noch komplexer. Es ist aber meiner Meinung technisch möglich und durch einen geschickten Projektbau inkl. SmartEdit UX auch bedienbar.
 

Schritt 5 - SmartEdit

Als letzten Schritt kann man sich nun Gedanken machen, da ja sowohl verknüpfen und verweisen möglich ist, wie man diese Lösung im SmartEdit entsprechend anbietet.
 

Erläuterung

Was passiert nun genau bei diesem Workaround. Dies ist recht schnell erklärt, wenn man sich die Syntax dieser Navigation-Manager Content-Klassen ansieht:

<%!! Store:Set(linkedContents,Context:CurrentIndex.Page.Elements.GetElement(Str:anchorNavigationCollector).GetLinkedContents()) !!%>
<%!! Store:Set(navigationAreaName,String:NavigationCollectorDepth) !!%>
<%!! Store:Set(navigationAreaNameLevel,Store:Get(navigationAreaName).Insert(Int:24,Context:CurrentDepth.ToString())) !!%>

<reddot:cms>
    <if>
        <query valuea="Store:Get(linkedContents).Count" operator="!=" valueb="Int:0">
            <foreach itemname="linkedPage" object="Store:Get(linkedContents)"></foreach> <!-- Workaround for "Get the GUID from linked page at anchor" -->
            <htmltext>
                <li><b><%!! Context:CurrentIndex.Page.Headline !!%></b><br>
                    <sup>(<%!! Store:Get(linkedPage).Id !!%> / <%!! Store:Get(linkedContents).Count !!%>)</sup>
                    <ul>
                        <%!! Navigation:OutputArea(Store:Get(navigationAreaNameLevel), Bool:False, Store:Get(linkedPage).Id) !!%>
                    </ul>
                </li></htmltext>
        </query>
        <query type="else">
            <htmltext>
                <li><b><%!! Context:CurrentIndex.Page.Headline !!%></b><br>
                <sup>(<%!! Context:CurrentIndex.Page.Id!!%> / <%!! Store:Get(linkedContents).Count !!%>)</sup>
            </htmltext>
            <if>
                <query valuea="Context:CurrentIndex.HasChildren()" operator="==" valueb="Bool:True">
                    <htmltext><ul><navigation:nextlevel></ul></htmltext>
                </query>
            </if>
            <htmltext></li></htmltext>
        </query>
    </if>
</reddot:cms>
  1. Als erstes wird das Objekt mit dem Inhalt an dem neu hinzugefügten Anchor-Element abgeholt.
  2. Danach wird die Tiefe in der aktuellen Navigation ermittelt, von der Seite mit dem befüllten Anchor-Element.
  3. Mit diesen Daten wird dann der Name der NavigationsArea berechnet bzw. erzeugt.
  1. Nun wird geprüft, ob wirklich Inhalte (also Verweise etc.) vorhanden sind.
  2. Wenn ja, dann wird die GUID der Seite ermittelt.
  1. Anschließend wird ein weiterer Navigationsbereich mit dem zuvor berechneten NavigationsArea-Namen und der GUID der Seite.
  1. Wenn keine Inhalte an dem Anchor-Element vorhanden sind, wird ganz normal die reguläre Navigation ermittelt und gerendert.

 

Bonus

Damit man jetzt nicht alles nachgebaut werden muss, habe ich das o.g. Beispiel als kleines Demo-Projekt gebaut und exportiert. Einfach diesen Projektexport (16.0.3.339) runterladen und importieren. Dann kann man sich diesen Workaround ansehen und damit rumspielen ;)


Über den Autor:
Thomas Pollinger

... ist Senior Site Reliability Engineer bei der Vodafone GmbH in Düsseldorf. Seit dem Jahr 2007 betreut er zusammen mit seinen Kollegen die OpenText- (vormals RedDot-) Plattform Web Site Management für die deutsche Konzernzentrale.

Er entwickelt Erweiterungen in Form von Plug-Ins und PowerShell Skripten. Seit den Anfängen in 2001 (RedDot CMS 4.0) kennt er sich speziell mit der Arbeitweise und den Funktionen des Management Server aus.