Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Bizzie 7 posts 27 karma points
    Nov 16, 2011 @ 19:25
    Bizzie
    0

    SubNav help needed please

    My subnav currently renders only the children of the current node. How do I get this to also render the parent node. Similarly how do I get it to render the child + parent node when on a grandchild node? In other words no matter on what level the displayed page is I’d like the subnav to display all children and grandchildren back up to their respective parent node whilst only displaying the child nodes if on parent (as it does at present).

    Home

    Parent 1

    Child 1

    Grandchild 1

    Grandchild 2

    Child 2

    Parent 2

    Child 1

    Grandchild 1

    Grandchild 2

    Child 2

    My current xslt is:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]>
    <xsl:stylesheet 
      version="1.0" 
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
      xmlns:msxml="urn:schemas-microsoft-com:xslt" 
      xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets" xmlns:tagsLib="urn:tagsLib" xmlns:BlogLibrary="urn:BlogLibrary" 
      exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets tagsLib BlogLibrary ">

    <xsl:output method="xml" omit-xml-declaration="yes"/>

    <xsl:param name="currentPage"/>

    <xsl:template match="/">

    <!-- The fun starts here -->
    <ul>
    <xsl:for-each select="$currentPage/* [@isDoc and string(umbracoNaviHide) != '1']">
      <li>
        <href="{umbraco.library:NiceUrl(@id)}">
          <xsl:value-of select="@nodeName"/>
        </a>
      </li>
    </xsl:for-each>
    </ul>

    </xsl:template>
    </xsl:stylesheet>

    I've tried lots of different ideas but my knowledge and understanding is lacking to say the least and I'd be very greatful for some help.

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 8x admin c-trib
    Nov 16, 2011 @ 21:15
    Chriztian Steinmeier
    0

     

    Hi Bizzie,

    Here's the approach that makes most sense for building navigation from scratch:

    You want to render a list item with a link for every page (Document) included in the nav - so create a template for that.

    Document nodes have an "isDoc" attribute so we'll match anything that has one of those:

    <!-- Template for a page -->
    <xsl:template match="*[@isDoc]">
        <li>
            <!-- Render the link to this page -->
            <a href="{umbraco.library:NiceUrl(@id)}">
                <xsl:value-of select="@nodeName" />
            </a>
        </li>
    </xsl:template>
    

    Then to render the actual nav, you start it off in the root template (match="/") - but instead of using $currentPage/blah-blah, do yourself a favor and create a siteRoot variable right away - it makes it so much easier to understand what's going on:

    <!-- Set a variable for the Home node of the website (usually at level 1) -->
    <xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 1]" />
    
    <xsl:template match="/">
        <ul>
            <!-- Start the navigation by rendering children of $siteRoot -->
            <xsl:apply-templates select="$siteRoot/*[@isDoc]" />
        </ul>
    </xsl:template>
    

    So far so good - now, you want to render childnodes too, so modify the Document template to check for those and start a new <ul> if present and then use the magic of <xsl:apply-templates /> to recurse down the tree, rendering children, grandchildren etc.:

    <!-- Template for a page -->
    <xsl:template match="*[@isDoc]">
        <li>
            <!-- Render the link to this page -->
            <a href="{umbraco.library:NiceUrl(@id)}">
                <xsl:value-of select="@nodeName" />
            </a>
            <!-- Render children (if any) -->
            <xsl:if test="*[@isDoc]">
                <ul>
                    <xsl:apply-templates select="*[@isDoc]" />
                </ul>
            </xsl:if>
        </li>
    </xsl:template>
    
    So the final XSLT looks something like this (not concerned about hidden nodes for now):

    <?xml version="1.0" encoding="utf-8" ?>
    <xsl:stylesheet
        version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:umbraco.library="urn:umbraco.library"
        exclude-result-prefixes="umbraco.library"
    >
    
        <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
    
        <xsl:param name="currentPage" />
    
        <!-- Set a variable for the Home node of the website (usually at level 1) -->
        <xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 1]" />
    
        <xsl:template match="/">
            <ul>
                <!-- Start the navigation by rendering children of $siteRoot -->
                <xsl:apply-templates select="$siteRoot/*[@isDoc]" />
            </ul>
        </xsl:template>
    
        <!-- Template for a page -->
        <xsl:template match="*[@isDoc]">
            <li>
                <!-- Render the link to this page -->
                <a href="{umbraco.library:NiceUrl(@id)}">
                    <xsl:value-of select="@nodeName" />
                </a>
                <!-- Render children (if any) -->
                <xsl:if test="*[@isDoc]">
                    <ul>
                        <xsl:apply-templates select="*[@isDoc]" />
                    </ul>
                </xsl:if>
            </li>
        </xsl:template>
    
    </xsl:stylesheet>
    

    Now get that to work and then come back here with the other requirements :-)

    /Chriztian

     

  • Bizzie 7 posts 27 karma points
    Nov 17, 2011 @ 13:27
    Bizzie
    0

    Hi Chriztian

    Many thanks for your time and clear explanations.

    I've now got all pages included in the SubNav as per your instructions. As it's a sub nav I don't want all pages and I'm back now for the other requirements.

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 8x admin c-trib
    Nov 17, 2011 @ 13:47
    Chriztian Steinmeier
    0

    Great - so 1st up is getting only the "current tree", which you get by adding a criterion to the existing test, to look for currentPage somewhere below (or at) the node being rendered:

    <!-- Template for a page -->
    <xsl:template match="*[@isDoc]">
            <li>
                    <!-- Render the link to this page -->
                    <a href="{umbraco.library:NiceUrl(@id)}">
                            <xsl:value-of select="@nodeName" />
                    </a>
                    <!-- Render children (if currentPage is in this branch) -->
                    <xsl:if test="descendant-or-self::*[@id = $currentPage/@id]">
                            <ul>
                                    <xsl:apply-templates select="*[@isDoc]" />
                            </ul>
                    </xsl:if>
            </li>
    </xsl:template>

    This should make sure that only one branch is expanded - the one containing $currentPage.

    This is all "standard" navigation behavior, but then comes your requirement - if you're on on of the "top level" pages ("Parent 1" or "Parent2") you only want the next level displayed, right? But do you want to expand both, or only the one you're on?

    Let me know if my assumptions are correct - then we'll continue from there.

    /Chriztian

     

  • Bizzie 7 posts 27 karma points
    Nov 17, 2011 @ 14:17
    Bizzie
    0

    I've now got too many nav items listed.

    As it's a subnav I've changed this

      <xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 2]" />

    to start at level 2 but I still have too many on all the pages.

    My original sub nav did go down the tree correctly but I want it to also display all the lelels up to their respective parents.

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 8x admin c-trib
    Nov 18, 2011 @ 15:09
    Chriztian Steinmeier
    0

    Hi Bizzie,

    By "too many", which do you mean? - Could you maybe show what you get compared to what you want?

    It's just a matter of tweaking the select's to get the correct nodes (as you already did with the $siteRoot).

    /Chriztian 

     

  • sun 403 posts 395 karma points
    Nov 18, 2011 @ 15:31
    sun
    0

    <href="{umbraco.library:NiceUrl(@id)}">
                            <xsl:if test="$currentPage/ancestor-or-self::*[@level=2]/@id=@id">
                                <xsl:attribute name="class"active</xsl:attribute>
                            </xsl:if>
                                <xsl:value-of select="@nodeName"/>
                        </a>

    give "a" tag a special class name "active", then use css to specialize it.

    I use this way to highlight main menu item which sub menu are active.

    Hope this can give you help

  • Bizzie 7 posts 27 karma points
    Nov 18, 2011 @ 16:53
    Bizzie
    0

    Hi Chriztian, I'm so glad you didn't abandon me!

    What I mean by too many is that your xslt displays all the level 2 nodes even when a level 3 has been selected and I want to display only the level 2 of that particular level 3 (child). I've got all the nodes from level 2 which is good for the main categories. When I select the main category node all the main categories are still there with the addition of the child of the selected node.

    What I want to achieve is when on level 3 to also display level 2 and when on level 4 to also display level 3 and 2.

    In my original xslt the only way a user has to navigate back to the parent (level 1) is to use the breadcrumb navigation.

    Basically what I want is the same as a breadcrumb (a way for the user to navigate back up the tree to its respective parent) without displaying all of the level 2 nodes. Hope this makes sense.

Please Sign in or register to post replies

Write your reply to:

Draft