Copied to clipboard

Flag this post as spam?

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


  • Sam 184 posts 209 karma points
    Apr 17, 2011 @ 11:46
    Sam
    0

    Expanding menu xslt

    Hi everyone,

    I have been modifyiny Chriztians menu to suit my website but I have run into a problem. Here is my code:

    <?xml version="1.0" encoding="utf-8" ?>
    <xsl:stylesheet
            version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:umb="urn:umbraco.library"
            exclude-result-prefixes="umb">

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

            <xsl:param name="currentPage" />
            <xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 2]" />
            
            <xsl:template match="/">
              <xsl:if test="count($currentPage/ancestor-or-self::* [@level=2]/* [@isDoc and string(umbracoNaviHide) != '1']) &gt; 0">
                <ul class="subMenu">
                    <li class="menuHeader">Browse sections</li>
                            <!-- Start with children of the site root -->
                            <xsl:apply-templates select="$siteRoot/*[@isDoc]" />
                    </ul>
                </xsl:if>
            </xsl:template>
            
            <xsl:template match="*[@isDoc]">
                    <li>
                            <a href="{umb:NiceUrl(@id)}">
                                               <xsl:if test="$currentPage/@id = current()/@id">
                        <xsl:attribute name="class">current</xsl:attribute>
                      </xsl:if>
                                    <xsl:value-of select="@nodeName" />
                            </a>
                            <!-- Make sure there is at least one visible page below, otherwise we get an empty <ul/> -->
                            <!-- If you need to stop at some level, do that here, like this: -->
                            <!-- <xsl:if test="*[@isDoc][not(umbracoNaviHide = 1)][not(level &gt; 4)]"> -->
                            <xsl:if test="$currentPage/*[@isDoc][$currentPage/@id = current()/@id]/ancestor-or-self::* [not(umbracoNaviHide = 1)]">
                                    <ul>
                                            <xsl:apply-templates select="*[@isDoc]" />
                                    </ul>
                            </xsl:if>
                    </li>
            </xsl:template>
            
            <!-- This automatically hides items with umbracoNaviHide checked -->
            <xsl:template match="*[umbracoNaviHide = 1]" />

    </xsl:stylesheet>

    So the menu only displays when a top level page has children, good so far. However, the child pages of the level 2 nodes are causing me a problem. The menu expands as I wanted it to when clicking on a level 2 page showing the level 3 pages underneath.

    The code above works until I click on one of the level 3 child pages, then the level 3 <ul> disappears as they don't fulfil the criteria of the test.

    Can anyone help me with the test? This is the problem area I think:

                            <xsl:if test="$currentPage/*[@isDoc][$currentPage/@id = current()/@id]/ancestor-or-self::* [not(umbracoNaviHide = 1)]">
                                    <ul>
                                            <xsl:apply-templates select="*[@isDoc]" />
                                    </ul>
                            </xsl:if>

    This is correct (MENU A):

    <ul class="subMenu">
    <li class="menuHeader">Browse sections</li>
    <li>
    <a href="#">Link 1</a>
    </li>
    <li>
    <a href="#">Link 2</a>
    </li>
    </ul>

    and clicking on the top one gives you this:

    <ul class="subMenu">
    <li class="menuHeader">Browse sections</li>
    <li>
    <a href="#" class="current">Link 1</a>
    <ul>
    <li>
    <a href="#">Link 1-1</a>
    </li>
    <li>
    <a href="#">Link 1-2</a>
    </li>
    <li>
    <a href="#">Link 1-3</a>
    </li>
    <li>
    <a href="#">Link 1-4</a>
    </li>
    </ul>
    </li>
    <li>
    <a href="#">Link 2</a>
    </li>
    </ul>

    Which is all good until I click on 'Link 1-1' or 'Link 1-2' etc. then I'm back with MENU A.

    I always wanted to add a class="current" to any sub levels, but could do with the menu working first. I hope the above makes sense.

    Thanks in advance :)

    Sam.

     

     

     

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Apr 17, 2011 @ 22:00
    Chriztian Steinmeier
    1

    Hi Sam,

    Here's an updated version - make sure to check the differences with a diff program or similar, to familiarize yourself with the modifications :-) 

    <?xml version="1.0" encoding="utf-8" ?>
    <xsl:stylesheet
        version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:umb="urn:umbraco.library"
        exclude-result-prefixes="umb">
    
        <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
    
        <xsl:param name="currentPage" />
        <xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 2]" />
    
        <xsl:template match="/">
            <xsl:if test="$siteRoot/*[@isDoc][not(umbracoNaviHide = 1)]">
                <ul class="subMenu">
                    <li class="menuHeader">Browse sections</li>
                    <!-- Start with children of the site root -->
                    <xsl:apply-templates select="$siteRoot/*[@isDoc]" />
                </ul>
            </xsl:if>
        </xsl:template>
    
        <xsl:template match="*[@isDoc]">
            <li>
                <a href="{umb:NiceUrl(@id)}">
                    <!-- Check if $currentPage is below or at this level -->
                    <xsl:if test="descendant-or-self::*[@id = $currentPage/@id]">
                        <xsl:attribute name="class">current</xsl:attribute>
                    </xsl:if>
                    <xsl:value-of select="@nodeName" />
                </a>
    
                <!-- If currentPage is below or at this level AND there is at least one visible child -->
                <xsl:if test="descendant-or-self::*[@id = $currentPage/@id] and *[@isDoc][not(umbracoNaviHide = 1)]">
                    <ul>
                        <xsl:apply-templates select="*[@isDoc]" />
                    </ul>
                </xsl:if>
            </li>
        </xsl:template>
    
        <!-- This automatically hides items with umbracoNaviHide checked -->
        <xsl:template match="*[umbracoNaviHide = 1]" />
    
    </xsl:stylesheet>
    

    /Chriztian

  • Sam 184 posts 209 karma points
    Apr 18, 2011 @ 09:33
    Sam
    0

    Thanks Chriztian.

    It makes perfect sense :) I couldn't think of the correct test. I will try this later when I get in.

    The help is very much appreciated.

    Sam.

  • Sam 184 posts 209 karma points
    Apr 18, 2011 @ 22:29
    Sam
    0

    All works perfect. I changed the test to 'self' rather than 'descendant-or-self' as I only want one link class of "current" at any time. The above gave the class to the descendant too.

    Thanks again :)

    Sam.

Please Sign in or register to post replies

Write your reply to:

Draft