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 2800 posts 8791 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

  • 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