Copied to clipboard

Flag this post as spam?

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


  • Jesper Lysgaard 16 posts 76 karma points
    Nov 16, 2009 @ 13:50
    Jesper Lysgaard
    0

    Menu with individual styling

    Hi

    I'm a novice in umbraco and the macrodevelopment in XSLT, and I am trying to make a 2 level topmenu with individual styling on each menu item. Perhaps not a good starting point in Umbraco learning but here goes:

    Problem:
    When I select a submenu item I have to make 1level menu item and second level item active (some kind of highlighting). So I have to manipulate the class attributes with XSLT.
    It works fine with 1level but when I hit a secondlevel menu item all 'active' styling dissapappears. 

    My XSLT 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:param name="level" select="/macro/StartAtLevel"/>
    <xsl:template match="/">

    <xsl:call-template name="menu">
    <xsl:with-param name="level" select="$level"/>
    </xsl:call-template>
    </xsl:template>
    <xsl:template name="menu">
    <xsl:param name="level"/>
    <ul class="mainMenu">
    <xsl:if test="count($currentPage/ancestor-or-self::node [@level=$level]/node [string(data [@alias='umbracoNaviHide']) != '1']) &gt; '0'">
    <xsl:for-each select="$currentPage/ancestor-or-self::node [@level=$level]/node [string(data [@alias='umbracoNaviHide']) != '1']">
    <li>
    <xsl:attribute name="class">
    menu<xsl:value-of select="position() + 1"/> menu
    </xsl:attribute>
    <xsl:if test="$currentPage/@id = current()/@id">
    <xsl:attribute name="class">
    menu<xsl:value-of select="position() + 1"/> active
    </xsl:attribute>
    </xsl:if>
    <a href="{umbraco.library:NiceUrl(@id)}">
    <xsl:if test="$currentPage/@id = current()/@id">
    <xsl:attribute name="class">active</xsl:attribute>
    </xsl:if>
    <xsl:value-of select="@nodeName"/>
    </a>
    <div>
    <ul>
    <xsl:for-each select="current()/node [string(data [@alias='umbracoNaviHide']) != '1']">

    <li>

    <a href="{umbraco.library:NiceUrl(@id)}">

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

    <xsl:attribute name="class">active</xsl:attribute>

    </xsl:if>

    <xsl:value-of select="@nodeName"/>

    </a>

    </li>

    </xsl:for-each>

    </ul>

    </div>

    </li>

    </xsl:for-each>

    </xsl:if>

    </ul>

    </xsl:template>

     

    </xsl:stylesheet>


    Hope somebody can tell me where my XSLT is wrong.

    Thanks

    Jesper

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 8x admin c-trib
    Nov 16, 2009 @ 22:14
    Chriztian Steinmeier
    0

    Hi Jesper,

    To keep the 'active' info you need to check if the current node is in the ancestor axis of $currentPage (you're only checking if the current node is $currentPage).

    I'd do something like this:

    <?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:param name="level" select="/macro/StartAtLevel" />
    
        <xsl:template match="/">
            <ul class="mainMenu">
                <xsl:apply-templates select="$currentPage/ancestor-or-self::node[@level = $level]/node" />
            </ul>
        </xsl:template>
    
        <!-- Output template for nodes -->
        <xsl:template match="node">
            <xsl:variable name="uniqueclass" select="concat('menu', position() + 1)" />
            <li>
                <!-- class attribute only at the first level  -->
                <xsl:if test="@level = $level + 1">
                    <xsl:attribute name="class"><xsl:value-of select="concat($uniqueclass, ' menu')" /></xsl:attribute>
                    <xsl:if test="$currentPage/ancestor-or-self::node[@id = current()/@id]">
                        <xsl:attribute name="class"><xsl:value-of select="concat($uniqueclass, ' active')" /></xsl:attribute>
                    </xsl:if>
                </xsl:if>
    
                <!-- Create the link -->
                <a href="{umbraco.library:NiceUrl(@id)}">
                    <xsl:if test="$currentPage/@nodeName = current()/@nodeName">
                        <xsl:attribute name="class">active</xsl:attribute>
                    </xsl:if>
                    <xsl:value-of select="@nodeName" />
                </a>
    
                <!-- Test if any of the subnodes are visible (otherwise we could get an empty <ul />) -->
                <!-- If you want infinite levels, remove the ' and @level = $level + 1' part -->
                <xsl:if test="node[not(data[@alias = 'umbracoNaviHide'] = 1)] and @level = $level + 1">
                    <div>
                        <ul>
                            <xsl:apply-templates select="node" />
                        </ul>
                    </div>
                </xsl:if>
            </li>
        </xsl:template>
    
        <!-- Never output these (empty template) -->
        <xsl:template match="node[data[@alias = 'umbracoNaviHide'] = 1]" />
    
    </xsl:stylesheet>
    
    Also (but not XSLT-related): I'd prefer to use id attributes for the unique values...
    /Chriztian
  • Dirk De Grave 4541 posts 6021 karma points MVP 3x admin c-trib
    Nov 16, 2009 @ 22:37
    Dirk De Grave
    2

    Also have a look at this project. May be what you need. Ok, you won't learn so much from copy'n'paste, but may get you started.

     

    Cheers,

    /Dirk

  • Jesper Lysgaard 16 posts 76 karma points
    Nov 17, 2009 @ 12:20
    Jesper Lysgaard
    0

    Thank you both. I'm very grateful.

    /Jesper

Please Sign in or register to post replies

Write your reply to:

Draft