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 2800 posts 8791 karma points MVP 8x 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.

  • 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