rbitdd
Returning Responder

Frage zur Navigation / Anzahl der Elemente eines Ordners

Hallo zusammen.

Ich habe folgendes Problem:

Unser Designer war so "kreativ", dass er in Abhängigkeit der Anzahl der Unterordner unterschiedliche Designs des Navigationshintergrundes möchte :smileyangry:

Ich muss nun auf erster Ebene wissen, wie viele Menüpunkte Ebene zwei hat.

Mit Hilfe des Helpdesks (ich dachte ich hätte einen Fehler gefunden, hab's aber nur falsch verstanden) bin ich schon mal soweit:

$CMS_SET(counter,0)$


$CMS_FOR(folder,#nav.ref.parent.parent.parent.parent.getChildren(#nav.ref.parent.class))$

$CMS_IF(folder.getFolderLangSpec(#global.language).isVisible())$

$CMS_SET(counter,counter+1)$

$CMS_VALUE(folder.id)$

$CMS_END_IF$

$CMS_END_FOR$



Ich lasse mir die ID ausgeben, um zu überprüfen, welchen Menüpunkt er denn jetzt gerade zählt.

Mir ist ja noch klar, das in Abhängigkeit der Anzahl der "parent"s, die ich angebe, auch die entsprechende Menüebene durchgezählt wird, jedoch nicht, warum er nicht immer die gleiche Menüebene zählt. OK, habe das nochmal überprüft, habe auch das jetzt verstanden. D.h. das ganze würde sich vereinfachen lassen, wenn für jeden Ordner eine eigene Startseite besteht und nicht nur ein Startordner. Hier weiß ich jedoch nicht, ob das gewünscht, geschweige denn auf Dauer so sein wird. Ich kenn doch die Redakteure. Smiley Wink

Hat jemand eine Idee, wie ich herausfinde, wie viele Menüpunkte Ebene X hat?

Danke schon mal! Smiley Happy

0 Kudos
8 Replies
rbitdd
Returning Responder

Ich habe mich durch diesen Artikel inspirieren lassen! Smiley Happy

Dabei ist dann folgendes rausgekommen:

$CMS_TRIM(level:3, char:"\r\n")$
$CMS_SET(menu_count,0)$
$CMS_SET(menu_list, [])$

$-- alle ordner in tmpfolder und einzeln durchlaufen--$
$CMS_FOR(tmpfolder,#global.node.store.children(#global.node.parent.class))$
    $-- ueberpruefen, ob ordner sichtbar ist --$
    $CMS_IF(tmpfolder.getFolderLangSpec(#global.language).isVisible())$
       $-- wenn ja, dann dessen unterordner durchsuchen ... --$
        $CMS_FOR(otherfolder,tmpfolder.children(#global.node.parent.class))$
            $-- und ueberpruefen, ob diese sichtbar sind --$
            $CMS_IF(otherfolder.getFolderLangSpec(#global.language).isVisible())$
                $-- wenn ja, dann wird dieser Ordner gezaehlt --$
                $CMS_SET(menu_count,menu_count+1)$
            $CMS_END_IF$
        $CMS_END_FOR$
        $-- alle gezaehlten Ordner der Liste hinzufuegen --$
        $CMS_SET(menu_list,menu_list.add(menu_count))$
        $-- und Wert wieder zurueck setzen --$
        $CMS_SET(menu_count,0)$
    $CMS_END_IF$
$CMS_END_FOR$
$CMS_END_TRIM$

Für die Navigationsfunktion habe ich noch einen weiteren Counter angelegt:

$CMS_SET(navi_counter,0)$

Innerhalb der Navigationsfunktion frage ich dann ab, wie viele Einträge jetzt in der entsprechenden Ebene enhalten sind:

$CMS_IF(menu_list.get(navi_counter) == 5)$###hier Style-Klassen-Änderung###$CMS_END_IF$

Und im innerEndHTML wird der Counter dann eins hoch gezählt.

$CMS_SET(navi_counter,navi_counter+1)$]

Etwas "tricky", geht auch vielleicht einfacher (bin offen für Vorschläge Smiley Wink), aber es geht jetzt erst mal!Smiley Happy

0 Kudos
rbitdd
Returning Responder

Ich habe einen Fehler gefunden:

Das oben genannte funktioniert nur, wenn "#global.node.parent.class" vom Typen "de.espirit.firstspirit.store.access.sitestore.PageRefFolderImpl" ist.

Aber sobald die generierte Seite direkt im Sitestore (z.B. die Startseite) liegt, funktioniert das nicht, weil da "#global.node.parent.class" vom Typen "de.espirit.firstspirit.store.access.sitestore.SiteStoreRootImpl" ist.

"Kleiner" aber feiner Unterschied.

Jemand ne Idee?

0 Kudos
hoebbel
Crownpeak employee

Erstmal zwei Anmerkungen [da ich keine Zeit habe, das in Ruhe durchzulesen]

Wenn man wissen will, ob der _aktuelle_ Navigationspunkt sichtbare Kinder hat, hilft #nav.hasSubFolders() [gibt einen Boolean Wert zurück]

Will man den aktuellen Ordner in der Navigation haben, bekommt man den mittels #nav.folder

Mit den beiden Informationen soltle der Code bedeutend kürzer werden - und das Problem mit der Sitestore Wurzel auch nicht mehr auftreten Smiley Wink

Tut mir leid, dass ich diese Infos in de helpdesk Antwort nicht mirgeschickt hatte - leider war mir wohl doch nicht ganz bewusst, was Sie wollten Smiley Sad

0 Kudos
rbitdd
Returning Responder

Hallo Herr Höbbel,

ja, gut zu wissen, hilft aber leider nicht weiter. Smiley Sad

Ich muss wissen, wie viele sichtbare Kinder der Menüpunkt hat, nicht ob. Daher hilft #nav.hasSubFolders() nicht weiter.

Über #nav.folder denke ich nochmal nach, ob das weiterhelfen könnte! Smiley Wink

Ein Kollege hat sich meiner kurz erbarmt und sich mit mir dran gesetzt.

Wir lassen uns jetzt per

$CMS_FOR(items,#global.node.store.children)$
     $CMS_SET(folder_reference,items)$
$CMS_END_FOR$

ein Objekt vom Typen "PageRefFolderImpl" geben! (Eklig, oder? :smileygrin: Ich bezweifle auch, dass das IMMER funktioniert. Bisherige Tests sind aber immer positiv ausgefallen, da FS bei #global.node.store.children

wohl immer erst die einzelnen Seitenreferenzen und danach erst die Ordner auflistet.)

Die "forder_reference" dann an Stelle von "#global.node.parent.class" eingetragen und es läuft! Smiley Happy

(Merkwürdigerweise muss ich das aber an beiden Stellen ersetzen. Warum ist mir nicht ganz klar, aber auch im Moment relativ! Smiley Wink)

Sieht also jetzt so aus:

$CMS_TRIM(level:3, char:"\r\n")$
$CMS_SET(navi_counter,0)$
$CMS_SET(menu_count,0)$
$CMS_SET(menu_list, [])$

$CMS_FOR(items,#global.node.store.children)$
    $CMS_SET(folder_reference,items)$
$CMS_END_FOR$

$-- alle ordner in tmpfolder und einzeln durchlaufen--$
$CMS_FOR(tmpfolder,#global.node.store.children(folder_reference.class))$
    $-- ueberpruefen, ob ordner sichtbar ist --$
    $CMS_IF(tmpfolder.getFolderLangSpec(#global.language).isVisible())$
       $-- wenn ja, dann dessen unterordner durchsuchen ... --$
        $CMS_FOR(otherfolder,tmpfolder.children(folder_reference.class))$
            $-- und ueberpruefen, ob diese sichtbar sind --$
            $CMS_IF(otherfolder.getFolderLangSpec(#global.language).isVisible())$
                $-- wenn ja, dann wird dieser Ordner gezaehlt --$
                $CMS_SET(menu_count,menu_count+1)$
            $CMS_END_IF$
        $CMS_END_FOR$
        $-- alle gezaehlten Ordner der Liste hinzufuegen --$
        $CMS_SET(menu_list,menu_list.add(menu_count))$

        $-- und Wert wieder zurueck setzen --$

        $CMS_SET(menu_count,0)$
    $CMS_END_IF$
$CMS_END_FOR$
$CMS_END_TRIM$

Mal schau'n ob sich das nicht doch noch optimieren lässt! Smiley Wink

Ach ja, meine tolles Konstrukt befindet sich nicht in der Navigationsfunktion. Daher werde ich, solange wir keinen Weg finden die Funktion komplett darin abzubilden, auch nicht auf #nav zu greifen können.

Viele Grüße

0 Kudos
rbitdd
Returning Responder

Ok, ich muss das hier nochmal ausgraben:

Wir lassen uns jetzt per

$CMS_FOR(items,#global.node.store.children)$
     $CMS_SET(folder_reference,items)$
$CMS_END_FOR$

ein Objekt vom Typen "PageRefFolderImpl" geben! (Eklig, oder? :smileygrin: Ich bezweifle auch, dass das IMMER funktioniert. Bisherige Tests sind aber immer positiv ausgefallen, da FS bei #global.node.store.children

wohl immer erst die einzelnen Seitenreferenzen und danach erst die Ordner auflistet.)

Also, eklig ist hier echt untertrieben. Ich habe jetzt herausgefunden, warum das funktionierte (und heute zwischenzeitlich nicht mehr! Smiley Wink :smileygrin:)


#global.node.store.children

zeigt nämlich nicht immer erst auf die Seiten und dann auf Ordner. Von Sortierung nach Typen kann hier keine Rede sein. Die ist dem FS ziemlich schnuppe. Es erfolgt viel mehr eine Sortierung nach ID. Diese ist, logischerweise, aufsteigend sortiert und bekanntermaßen von der Reihenfolge der Anlage des Objektes abhängig.

Wenn ich also zuletzt im Strukturbaum an oberster Stelle eine Seite angelegt habe, erhalte ich unter "folder_reference" eine Seite und mein tolles Skript war für'n "Hintern".

Derzeit habe ich jedoch das Glück, das ich eine Strukturvariable setzen musste, die auf einen Ordner verweist und das wird auch immer so bleiben. Daher ist es zuverlässiger als die bisherige Variante, wenn ich mir von dieser Variable die Referenz bzw. die Klasse der Referenz geben lasse.

Ich wünschte eine bessere Lösung präsentieren zu können. Vielleicht findet sich diese ja noch! Smiley Wink

In diesem Sinne: t.b.c.

0 Kudos

Hallo rbitdd,

falls ich den Sachverhalt richtig verstanden habe könnte es auch so gelöste werden:

<CMS_HEADER>
 
<CMS_FUNCTION name="Navigation" resultname="fr_pt_mainnavigation">
  <CMS_PARAM name="expansionVisibility" value="all"/>
  <CMS_PARAM name="wholePathSelected" value="1"/>
  <CMS_PARAM name="suppressEmptyFolders" value="1" />
  <CMS_ARRAY_PARAM name="beginHTML" size="5">
    <CMS_ARRAY_ELEMENT index="0">
    <![CDATA[
    $CMS_SET(level_0_count,0)$
    $CMS_SET(level_0_content,"")$
    ]]></CMS_ARRAY_ELEMENT>
    <CMS_ARRAY_ELEMENT index="1">
    <![CDATA[
    $CMS_SET(level_1_count,0)$
    $CMS_SET(level_0_count,level_0_count + 1)$
    $CMS_SET(level_1_content,"")$
    ]]></CMS_ARRAY_ELEMENT>
    <CMS_ARRAY_ELEMENT index="2">
    <![CDATA[
    $CMS_SET(level_2_count,0)$
    $CMS_SET(level_1_count,level_1_count + 1)$
    $CMS_SET(level_2_content,"")$
    ]]></CMS_ARRAY_ELEMENT>
    <CMS_ARRAY_ELEMENT index="3">
    <![CDATA[
    $CMS_SET(level_3_count,0)$
    $CMS_SET(level_2_count,level_2_count + 1)$
    $CMS_SET(level_3_content,"")$
    ]]></CMS_ARRAY_ELEMENT>
    <CMS_ARRAY_ELEMENT index="4">
    <![CDATA[
    $CMS_SET(level_4_count,0)$
    $CMS_SET(level_3_count,level_3_count + 1)$
    $CMS_SET(level_4_content,"")$
    ]]></CMS_ARRAY_ELEMENT>
    </CMS_ARRAY_PARAM>
 
  <CMS_ARRAY_PARAM name="endHTML" size="5">
    <CMS_ARRAY_ELEMENT index="0">
    <![CDATA[<div>$CMS_VALUE(#nav.label)$ ($CMS_VALUE(level_0_count)$)</div>
    $CMS_VALUE(level_0_content)$
    ]]></CMS_ARRAY_ELEMENT>
    <CMS_ARRAY_ELEMENT index="1">
    <![CDATA[
    $CMS_SET(level_0_content_new)$<div>$CMS_VALUE(#nav.label)$ ($CMS_VALUE(level_1_count)$)</div>$CMS_END_SET$
    $CMS_SET(level_0_content,level_0_content.toString()+level_0_content_new.toString()+level_1_content.toString())$
    ]]></CMS_ARRAY_ELEMENT>
    <CMS_ARRAY_ELEMENT index="2">
    <![CDATA[
    $CMS_SET(level_1_content_new)$<div>$CMS_VALUE(#nav.label)$ ($CMS_VALUE(level_2_count)$)</div>$CMS_END_SET$
    $CMS_SET(level_1_content,level_1_content.toString()+level_1_content_new.toString()+level_2_content.toString())$
    ]]></CMS_ARRAY_ELEMENT>
    <CMS_ARRAY_ELEMENT index="3">
    <![CDATA[
    $CMS_SET(level_2_content_new)$<div>$CMS_VALUE(#nav.label)$ ($CMS_VALUE(level_3_count)$)</div>$CMS_END_SET$
    $CMS_SET(level_2_content,level_2_content.toString()+level_2_content_new.toString()+level_3_content.toString())$
    ]]></CMS_ARRAY_ELEMENT>
    <CMS_ARRAY_ELEMENT index="4">
    <![CDATA[
    $CMS_SET(level_3_content_new)$<div>$CMS_VALUE(#nav.label)$ ($CMS_VALUE(level_4_count)$)</div>$CMS_END_SET$
    $CMS_SET(level_3_content,level_3_content.toString()+level_3_content_new.toString()+level_4_content.toString())$
    ]]></CMS_ARRAY_ELEMENT>
    </CMS_ARRAY_PARAM>
</CMS_FUNCTION>
</CMS_HEADER>
<style type="text/css">
.level0{padding-left:0px;}
.level1{padding-left:20px;}
.level2{padding-left:40px;}
.level3{padding-left:60px;}
.level4{padding-left:80px;}
.level5{padding-left:100px;}
</style>
$CMS_VALUE(fr_pt_mainnavigation)$

Ich hoffe es hilft das Problem zu lösen.

Beste Grüße aus Ulm

0 Kudos

Hallo rbitdd,

ist das Thema noch aktuell? Ich habe ähnliche Probleme über ein Script gelöst. Es wir innerhalb der Funktion navigation aufgerufen und bekommt den aktuellen Navigationspunkt und die Sprache übergeben (beides kenne ich an diesem Punkt und erspare mir so das umständliche holen über den Rendercontext). Das sieht dann so aus:

     $CMS_RENDER(script:"shownavarrow",nav:#nav,lang:#global.language)$

Der Rückgabewert kann entweder ein String für die CSS Classe sein oder eine Zahl für die Verarbeitung im Template. Je nach dem, wie oft man dieses Script in anderem Context benötigt, muss man sich für eine Variante entscheiden.

Im Scritp hole ich mir über

     PageRefFolder parentFolder = nav.getFolder();

den übergeordneten Ordner, über den ich dann iterieren kann:

    int folderCount = 0;  

    folderIter = parentFolder.getChildren(PageRefFolder.class, false).iterator();
    while(folderIter.hasNext()){
        if(folderIter.next().getFolderLangSpec(lang).isVisible()){
            folderCount++;           
        }
    }

Danach kann man die Zahl nach Belieben weiter verarbeiten und am Ende des Scripts über den Return das gewünschte Resultat zurückgeben oder in eine globale Variable speichern (einen Hinweis, wie das geht, findet man in einem Blog von Gerrit Bösebeck). Schreibt man das CMS_RENDER in ein CMS_SET, kann man diese Variable ebenfalls weiter verwenden.

Abschließend ist noch zu sagen, dass man im Script die try and catch Anweisungen nicht vergessen sollte und ein paar wenige Logs für das Debugging einbauen, dann geht die Entwicklung einfacher 😉

Ich hoffe, der Ansatz hilft.

Viele Grüße.

PS: Die o.g. Methode hasSubFolders() liefert alle Unterordner unabhängig von ihrer Sichtbarkeit in der Navigation bzw. Sitemap.

0 Kudos

Sorry für den Necro, aber das Thema ist noch immer nicht im Produkt gelöst.

Vielleicht mag der eine oder die andere meinen FR unterstützen?

https://community.crownpeak.com/t5/Feature-Discussions/New-nav-hasVisibleSubFolders-Function/idi-p/5...

0 Kudos