Copied to clipboard

Flag this post as spam?

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


  • Kris Anderson 12 posts 32 karma points
    Jan 23, 2011 @ 08:37
    Kris Anderson
    0

    Need help with sub-navigation XSLT

    Hey everyone,

    I'm still new to Umbraco and don't fully understand XSLT yet, so I'm having trouble getting my sub-navigation working.

    I have my sub-navigation working in a single level, but I want to be able to drill down another level when needed. I basically want to be able to add a <ul class="lv2"> HTML tag within my current <ul class="lv1"> tag and then style that with CSS so it looks like a sub level of the currently selected level.

    To better explain, my sub-navigation looks like this:

    Some Topic
    Another Topic
    Third Topic

    But when "Another Topic" is selected, I want it to look like is:

    Some Topic
    Another Topic
       Something Here
       Another Something
    Third topic

    I know how to do this in HTML and CSS, I'm just not sure how to get there in XLST. Here is my current SubNavigation.xlst file:

    <?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" xmlns:PS.XSLTsearch="urn:PS.XSLTsearch"
      exclude-result-prefixes="msxml
    umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes
    Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings
    Exslt.ExsltSets tagsLib BlogLibrary PS.XSLTsearch "
    >

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

    <xsl:param name="currentPage"/>

    <!-- Input the documenttype you want here -->
    <xsl:variable name="level" select="2"/>

    <xsl:template match="/">

    <!-- The fun starts here -->
    <ul class="lv1">
      <xsl:variable name="mainNavPage" select="$currentPage/ancestor-or-self::* [@level=$level]"/>
      <li>
        <xsl:if test="$currentPage/@id = $mainNavPage/@id">
          <xsl:attribute name="class">selected</xsl:attribute>
        </xsl:if>
    <xsl:if test="string($mainNavPage/@id) != ''">
    <a href="{umbraco.library:NiceUrl($mainNavPage/@id)}/">
          <xsl:if test="$currentPage/@id = $mainNavPage/@id">
          <xsl:attribute name="class">selected</xsl:attribute>
        </xsl:if>
      <strong>
        <xsl:value-of select="$mainNavPage/@nodeName"/>
      </strong>
      <xsl:value-of select="$mainNavPage/navigationDescription" />
    </a>
    </xsl:if>

      </li>

    <xsl:for-each select="$currentPage/ancestor-or-self::* [@level=$level]/* [@isDoc and string(umbracoNaviHide) != '1']">
      <li>
        <xsl:if test="$currentPage/ancestor-or-self::*/@id = current()/@id">
          <xsl:attribute name="class">selected</xsl:attribute>
        </xsl:if>
        <a>
          <xsl:if test="$currentPage/ancestor-or-self::*/@id = current()/@id">
            <xsl:attribute name="class">selected</xsl:attribute>
          </xsl:if>
    <xsl:attribute name="href">
      <xsl:choose>
        <xsl:when test="string(displayAsDirectory) = '1'">
          <xsl:value-of select="concat(umbraco.library:NiceUrl(@id), '/')" />
        </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="concat(umbraco.library:NiceUrl(@id), '.aspx')" />       
          </xsl:otherwise>
      </xsl:choose>
    </xsl:attribute>
          <strong>
            <xsl:value-of select="@pageName" />
            <xsl:value-of select="@nodeName" />
          </strong>
          <xsl:value-of select="navigationDescription" />
        </a>
      </li>
    </xsl:for-each>
    </ul>

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

    I know the code I have to insert needs to go towards the end of that XSLT file before the following:

    </xsl:for-each>
    </ul>

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

    I've been playing around with this for a while now and I have the following code working:

      <xsl:if test="$currentPage/ancestor-or-self::*/@id = current()/@id">
      <xsl:for-each select="$currentPage/* [@isDoc and string(umbracoNaviHide) != '1']">
        <ul class="lv2">
          <li>
            <xsl:if test="$currentPage/ancestor-or-self::*/@id = current()/@id">
              <xsl:attribute name="class">selected</xsl:attribute>
            </xsl:if>
            <a href="{umbraco.library:NiceUrl(@id)}">
              <strong><xsl:value-of select="@nodeName"/></strong>
            </a>
          </li>
        </ul>
      </xsl:for-each>
      </xsl:if>

    The above code actually works when I'm viewing a 2nd level page. If a second level page is selected and it has 3rd level children below it, all of those child links show in the navigation. Works perfect right... just how I want it to. However, once I click on one of those 3rd level links, the navigation goes back to only showing 2 levels (when I want it to keep showing 3 levels). I would like to have my second level marked with class="selected", and also do the same for the third level. The problem is, the third level no longer shows.

    I know why this is happening. It's because I'm using that XSL IF statement. When I am on a third level page and this SubNavigation.xslt file is called, it finds my if statement and says there are no children. Therefor, no 3rd level pages are being shown.

    <xsl:if test="$currentPage/ancestor-or-self::*/@id = current()/@id">

    I probably just need one line of code to get this working... but I'm not sure what I can try. Can someone help point me in the right direction?

  • Daniel Bardi 924 posts 2556 karma points
    Jan 23, 2011 @ 09:26
    Daniel Bardi
    0

    Check if the current page equal to the navigation item

    <xsl:for-each .... >

    <xsl:if test="$currentPage/@id = current()/@id>

    ... show sub navigation ...

    </xsl:if>

    </xsl:for-each>

  • Daniel Bardi 924 posts 2556 karma points
    Jan 23, 2011 @ 09:27
    Daniel Bardi
    0

    Nevermind.. didn't read the entire post.

    Sorry!

  • Kris Anderson 12 posts 32 karma points
    Jan 23, 2011 @ 10:45
    Kris Anderson
    0

    I think I finally have this working. I downloaded some demo Umbraco sites and found a Koiak Standard Site that did the sub-navigation similar to what I wanted. I took their two lines of IF statements and modified it to suite my needs. This is the code I ended up with:

        <xsl:if test="current()/@level &lt; (6) and $currentPage/ancestor-or-self::*[@isDoc]/@id = current()/@id">
          <xsl:if test="count(*[@isDoc][not(data[@alias='umbracoNaviHide']=1)]) > 0">
            <ul class="lv2">
              <xsl:for-each select="*[@isDoc][not(data[@alias='umbracoNaviHide']=1)]">
                <li>
                  <xsl:if test="$currentPage/ancestor-or-self::*/@id = current()/@id">
                    <xsl:attribute name="class">selected</xsl:attribute>
                  </xsl:if>
                  <a href="{umbraco.library:NiceUrl(@id)}">
                    <xsl:if test="$currentPage/ancestor-or-self::*/@id = current()/@id">
                      <xsl:attribute name="class">selected</xsl:attribute>
                    </xsl:if>
                    <strong>
                      <xsl:value-of select="@nodeName"/>
                    </strong>
                  </a>
                </li>
              </xsl:for-each>
            </ul>
          </xsl:if>
        </xsl:if>

    Question though... is that the best way to do this? It appears to be working perfectly... but I'm not sure if there's a better way to be doing it. The two lines of code from the Koiak demo site that got this working for me were:

    <xsl:if test="current()/@level &lt; (6) and $currentPage/ancestor-or-self::*[@isDoc]/@id = current()/@id">
    <xsl:if test="count(*[@isDoc][not(data[@alias='umbracoNaviHide']=1)]) > 0">
  • Kim Andersen 1447 posts 2196 karma points MVP
    Jan 23, 2011 @ 13:34
    Kim Andersen
    0

    Hi Kris

    Often when I need a small and simple submenu eg. in a sidebar or something like that, I tend to use this piece of code:

    <xsl:variable name="rootNode" select="$currentPage/ancestor-or-self::*[@level=2]" />
    <xsl:template match="/">
    <h3 class="subMenuHeader">
    <a href="{umbraco.library:NiceUrl($rootNode/@id)}">
    <xsl:value-of select="$currentPage/ancestor-or-self::*[@level = '2']/@nodeName"/>
    </a>
    </h3>
    <ul id="subMenu">
    <xsl:apply-templates select="$rootNode/*[@isDoc and string(umbracoNaviHide) != '1']"/>
    <li class="hide">
    <p>&nbsp;</p>
    </li>
    </ul>
    </xsl:template>

    <xsl:template match="*[@isDoc and string(umbracoNaviHide) != '1']">
    <xsl:variable name="id" select="id" />
    <li class="subNiveau">
    <xsl:attribute name="class">subNiveau<xsl:if test="$currentPage/ancestor-or-self::*/@id = current()/@id"> current</xsl:if></xsl:attribute>
    <a href="{umbraco.library:NiceUrl(./@id)}">
    <xsl:value-of select="@nodeName" />
    </a>
    </li>
    <xsl:if test="count(./*[@isDoc and string(umbracoNaviHide) != '1']) &gt; 0 and count(descendant-or-self::*[@id = $currentPage/@id]) &gt; 0">
    <li class="subMenu2">
    <ul>
    <xsl:apply-templates select="./*[@isDoc and string(umbracoNaviHide) != '1']" />
    </ul>
    </li>
    </xsl:if>
    </xsl:template>

    What the above code does is of course to render a submenu. In the top of the menu, there's a link to the "main-menu-page". Of course this can be removed easily. The code will continue to add additional levels of nodes if they are present in the content tree.

    I don't know if this can inspire you, but now you've got the code for a quite easy submenu macro. Take it or leave it :)

    /Kim A

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies