Copied to clipboard

Flag this post as spam?

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


  • NightWolf 41 posts 44 karma points
    Dec 29, 2009 @ 23:58
    NightWolf
    0

    New umbraco content structure, sub navigation alternative

    I have build the last couple Umbraco website with the following structure and have found it really good especially from a client perspective:

    • Content
      • Home
      • Page 1
      • Page 2
      • Page 3

    Below is the XSLT I use to display the sub menu structure, just wondering if anyone can see a better way of doing this as it's still a manual process if at a later date the client want's to add an additional level to the menu.

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

      <xsl:param name="currentPage"/>

      <!-- Defines how many levels the drop down should have. -->
      <xsl:variable name="menuDepth" select="5" />

      <xsl:template match="/">
        <xsl:choose>
          <xsl:when test="$currentPage/@level = 5">
            <h4>
              <xsl:value-of select="$currentPage/parent::node/parent::node/@nodeName" />
            </h4>
            <xsl:call-template name="drawNodes">
              <xsl:with-param name="parent" select="umbraco.library:GetXmlNodeById($currentPage/parent::node/parent::node/@id)" />
            </xsl:call-template>
          </xsl:when>
          <xsl:when test="$currentPage/@level = 4">
            <h4>
              <xsl:value-of select="$currentPage/parent::node/@nodeName" />
            </h4>
            <xsl:call-template name="drawNodes">
              <xsl:with-param name="parent" select="umbraco.library:GetXmlNodeById($currentPage/parent::node/@id)" />
            </xsl:call-template>
          </xsl:when>
          <xsl:otherwise>
            <h4>
              <xsl:value-of select="$currentPage/@nodeName" />
            </h4>
            <xsl:call-template name="drawNodes">
              <xsl:with-param name="parent" select="umbraco.library:GetXmlNodeById($currentPage/@id)" />
            </xsl:call-template>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:template>

      <xsl:template name="drawNodes">
        <xsl:param name="parent" />

        <ul>
          <xsl:for-each select="$parent/node">
            <xsl:if test="string(./data [@alias = 'umbracoNaviHide']) != '1'">
            <li>
              <a href="{umbraco.library:NiceUrl(@id)}">
                <xsl:if test="$currentPage/@id = current()/@id">
                  <xsl:attribute name="class">activeItem</xsl:attribute>
                </xsl:if>
                <xsl:choose>
                  <xsl:when test="string-length(normalize-space(./data [@alias = 'naviTitle'])) = 0">
                    <xsl:value-of select="@nodeName" />
                  </xsl:when>
                  <xsl:otherwise>
                    <xsl:value-of select="./data [@alias = 'naviTitle']" />
                  </xsl:otherwise>
                </xsl:choose>
              </a>

              <xsl:if test="count(./node [string(./data [@alias = 'umbracoNaviHide']) != '1' and @level &lt;= $menuDepth]) &gt; 0">
                <xsl:call-template name="drawNodes">
                  <xsl:with-param name="parent" select="." />
                </xsl:call-template>
              </xsl:if>
            </li>
            </xsl:if>
          </xsl:for-each>
        </ul>
      </xsl:template>
    </xsl:stylesheet>

  • Chris Houston 535 posts 980 karma points MVP admin c-trib
    Dec 31, 2009 @ 13:32
    Chris Houston
    0

    Hi Nightwolf,

    The XSLT I use ( and sometimes modify depending on the client requirement ) for a menu is as follows:

    <?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"
    exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets ">


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

    <xsl:param name="currentPage"/>

    <xsl:template match="/">
    <xsl:call-template name="buildMenu">
    <xsl:with-param name="parent" select="$currentPage/ancestor-or-self::node [@level=2]"/>
    <xsl:with-param name="first" select="1"/>
    <xsl:with-param name="selectedPage" select="$currentPage"/>
    </xsl:call-template>
    </xsl:template>

    <xsl:template name="buildMenu">
    <xsl:param name="parent"/>
    <xsl:param name="first"/>
    <xsl:param name="selectedPage"/>
    <ul>
    <xsl:if test="$first = 1">
    <xsl:attribute name="class">sf-menu</xsl:attribute>
    </xsl:if>
    <xsl:for-each select="$parent/node">
    <xsl:variable name="hasNode">
    <xsl:choose>
    <xsl:when test="string(./@nodeTypeAlias) = 'redirectPage'">
    1
    </xsl:when>
    <xsl:when test="./data[@alias = 'umbracoNaviHide'] != 1">
    1
    </xsl:when>
    <xsl:when test="string(./@nodeTypeAlias) = 'umbracoBlog'">
    1
    </xsl:when>
    <xsl:otherwise>
    0
    </xsl:otherwise>
    </xsl:choose>

    </xsl:variable>
    <xsl:if test="$hasNode=1">
    <li>
    <a>
    <xsl:choose>
    <xsl:when test="string(./@nodeTypeAlias) = 'redirectPage'">
    <xsl:attribute name="href"><xsl:value-of select="./data[@alias='redirectPage']" /></xsl:attribute>
    </xsl:when>
    <xsl:otherwise>
    <xsl:attribute name="href"><xsl:value-of select="umbraco.library:NiceUrl(@id)" /></xsl:attribute>
    </xsl:otherwise>
    </xsl:choose>
    <xsl:if test="contains($selectedPage/@path,@id)">
    <xsl:attribute name="class">selected</xsl:attribute>
    </xsl:if>
    <xsl:value-of select="@nodeName" />
    </a>
    <xsl:if test="count(current()/child::node[string(data[@alias='umbracoNaviHide']) = '0']) > 0">
    <xsl:call-template name="buildMenu">
    <xsl:with-param name="parent" select=". "/>
    <xsl:with-param name="selectedPage" select="$selectedPage"/>
    </xsl:call-template>
    </xsl:if>
    </li>
    </xsl:if>
    </xsl:for-each>
    </ul>
    </xsl:template>

    </xsl:stylesheet>

    Just a couple of pointers with this script, I pass in a parameter first so that the top level UL has a CSS class set, that way you can define your CSS for the menu based on that class.

    Also the script is checking if a node is type is called  redirectPage as this allows you to have menu items that re-direct externally.

    I have hard coded the Level = 2 which is the start level for the menu structure, as this is very unlikely to ever change once a site has been built.

    There is no maximum depth but you could of course add that within the IF statement that checks for child nodes and you could pass this parameter in as a macro variable so the user can set the depth.

    Cheers,

    Chris

Please Sign in or register to post replies

Write your reply to:

Draft