Copied to clipboard

Flag this post as spam?

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


  • syn-rg 282 posts 425 karma points
    May 02, 2012 @ 09:01
    syn-rg
    0

    Multi-level 2nd level menu with "Current" style

    I'm creating a multi level 2nd level menu.

    My current XSLT is creating the list but adding the parent node, into the child node list. So I'm getting a repeat of the parent node in the child node list.

    Also I want to add a "current" CSS style to the current "li", and for any parent nodes to display as current if the child node is current.

    Can anyone help me fix these two issues?

    Cheers, JV

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


    <xsl:output method="xml" omit-xml-declaration="yes"/>
      
    <!-- update this variable on how deep your navigation should be -->
    <xsl:variable name="level2" select="$currentPage/ancestor-or-self::* [@level = 2]" />
    <xsl:variable name="level3" select="$currentPage/ancestor-or-self::* [@level = 3]" />
    <!--<xsl:variable name="level3" select="$currentPage/ancestor-or-self::* [@isDoc and @level = 2]/* [@isDoc and string(umbracoNaviHide) != '1']"/>
    <xsl:variable name="level4" select="$currentPage/ancestor-or-self::* [@isDoc and @level = 3]/* [@isDoc and string(umbracoNaviHide) != '1']"/>-->

    <xsl:param name="currentPage"/>
      
    <xsl:template match="/">
      
      <div class="subnav">
        <!-- LEVEL 2 -->
        <xsl:if test="$level2 != ''">
          <a href="{umbraco.library:NiceUrl($level2/@id)}">
            <xsl:if test="$level2/@id = $currentPage/@id">
              <xsl:attribute name="class">current</xsl:attribute>
            </xsl:if>
            <xsl:value-of select="$level2/@nodeName"/>
          </a>
        </xsl:if>
        <!-- SIDE MENU -->
        <ul>
          <xsl:call-template name="drawNodes">
            <xsl:with-param name="parent" select="$currentPage/ancestor-or-self::*[@level=2]"/>
          </xsl:call-template>
        </ul>
      </div>

    </xsl:template>


    <xsl:template name="drawNodes">
      <xsl:param name="parent"/>
      
      <xsl:for-each select="$parent/* [@isDoc]">
        <li>
          <a>
            <xsl:if test="$currentPage/descendant-or-self::*/@id = @id ">
              <xsl:attribute name="class">current</xsl:attribute>
            </xsl:if>
            <xsl:attribute name="href">
              <xsl:value-of select="umbraco.library:NiceUrl(@id)" />
            </xsl:attribute>
            <xsl:value-of select="@nodeName"/>
          </a>
          <xsl:if test="count(./child::*[@isDoc and string(umbracoNaviHide) != '1' and string(@template) != '0']) &gt; 0">   
            <ul>
              <li>
                <a>
                  <xsl:if test="$currentPage/descendant-or-self::*/@id = @id ">
                    <xsl:attribute name="class">current</xsl:attribute>
                  </xsl:if>
                  <xsl:attribute name="href">
                    <xsl:value-of select="umbraco.library:NiceUrl(@id)" />
                  </xsl:attribute>
                  <xsl:value-of select="@nodeName"/>
                </a>
              </li>
              <xsl:call-template name="drawNodes">
                <xsl:with-param name="parent" select="."/>
              </xsl:call-template>
            </ul>
          </xsl:if>
        </li>
      </xsl:for-each>
    </xsl:template>


    </xsl:stylesheet>
  • syn-rg 282 posts 425 karma points
    May 03, 2012 @ 04:02
    syn-rg
    0

    I've got the "current" state working for the current "li".

    But I'm still getting the parent node repeating in the child node list.

    Example of results:
    About
    What we do
    ---What we do (The parent is repeated here!)
    ---Who we are
    ---Where we come from
    Our staff
    etc

    Here's my updated XSLT:

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


    <xsl:output method="xml" omit-xml-declaration="yes"/>
      
    <!-- update this variable on how deep your navigation should be -->
    <xsl:variable name="level2" select="$currentPage/ancestor-or-self::* [@level = 2]" />
    <xsl:variable name="level3" select="$currentPage/ancestor-or-self::* [@level = 3]" />
    <!--<xsl:variable name="level3" select="$currentPage/ancestor-or-self::* [@isDoc and @level = 2]/* [@isDoc and string(umbracoNaviHide) != '1']"/>
    <xsl:variable name="level4" select="$currentPage/ancestor-or-self::* [@isDoc and @level = 3]/* [@isDoc and string(umbracoNaviHide) != '1']"/>-->

    <xsl:param name="currentPage"/>
      
    <xsl:template match="/">
      
      <div class="subnav">
        <!-- LEVEL 2 -->
        <xsl:if test="$level2 != ''">
          <a href="{umbraco.library:NiceUrl($level2/@id)}">
            <xsl:if test="$level2/@id = $currentPage/@id">
              <xsl:attribute name="class">current</xsl:attribute>
            </xsl:if>
            <xsl:value-of select="$level2/@nodeName"/>
          </a>
        </xsl:if>
        <!-- SIDE MENU -->
        <ul>
          <xsl:call-template name="drawNodes">
            <xsl:with-param name="parent" select="$currentPage/ancestor-or-self::*[@level=2]"/>
          </xsl:call-template>
        </ul>
      </div>

    </xsl:template>


    <xsl:template name="drawNodes">
      <xsl:param name="parent"/>
      
      <xsl:for-each select="$parent/* [@isDoc]">
        <li>
            <xsl:if test="$currentPage/ancestor-or-self::*/@id = @id ">
              <xsl:attribute name="class">current</xsl:attribute>
            </xsl:if>
          <a>
            <xsl:attribute name="href">
              <xsl:value-of select="umbraco.library:NiceUrl(@id)" />
            </xsl:attribute>
            <xsl:value-of select="@nodeName"/>
          </a>
          <xsl:if test="count(./child::*[@isDoc and string(umbracoNaviHide) != '1' and string(@template) != '0']) &gt; 0">   
            <ul>
              <li>
                  <xsl:if test="$currentPage/ancestor-or-self::*/@id = @id ">
                    <xsl:attribute name="class">current</xsl:attribute>
                  </xsl:if>
                <a>
                  <xsl:attribute name="href">
                    <xsl:value-of select="umbraco.library:NiceUrl(@id)" />
                  </xsl:attribute>
                  <xsl:value-of select="@nodeName"/>
                </a>
              </li>
              <xsl:call-template name="drawNodes">
                <xsl:with-param name="parent" select="."/>
              </xsl:call-template>
            </ul>
          </xsl:if>
        </li>
      </xsl:for-each>
    </xsl:template>


    </xsl:stylesheet>

     

  • Fuji Kusaka 2203 posts 4220 karma points
    May 03, 2012 @ 06:43
    Fuji Kusaka
    1

    Hi JV,

    You could also do something like

    <xsl:variable name="level" select="2"/>
     
    <xsl:template match="/">

    <!-- The fun starts here -->
    <div class="subnav">  
       <xsl:for-each select="$currentPage/ancestor-or-self::* [@level=$level]/* [@isDoc and string(umbracoNaviHide) != '1']">
    <xsl:element name="li">       
    <xsl:attribute name="class">          
    <xsl:if test="$currentPage/ancestor-or-self::*[@isDoc]/@id = current()/@id">              
    <xsl:text> current</xsl:text>          
    </xsl:if>     
     
    </xsl:attribute>     
     
    <a href="{umbraco.library:NiceUrl(@id)}">      
    <xsl:value-of select="@nodeName"/>    
    </a>
    <!-- Level 3 if any more nodes are Visible -->

    <xsl:if test="*[@isDoc][not(umbracoNaviHide = 1)]">    
     <xsl:for-each select="./* [@isDoc  and string(umbracoNaviHide) != '1']">           
    <xsl:value-of select="@nodeName" />                 
    </xsl:for-each>               
    </xsl:if>
    </xsl:element >
    </xsl:for-each>
    </div>
    </xsl:template>

    Hope it helps

  • syn-rg 282 posts 425 karma points
    May 03, 2012 @ 07:41
    syn-rg
    0

    Hi Fuji,

    Thanks for that, I've made some amends to your suggestion and have got it work to level 4.

    However I want something that I could have unlimited levels, but have a variable for it stop at a maximum amount of levels.

    Here's the amended XSLT:

    <?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"
      exclude-result-prefixes="msxml umbraco.library">
        
    <xsl:output method="xml" omit-xml-declaration="yes"/>

    <xsl:param name="currentPage"/>
     
    <xsl:template match="/">
    <xsl:variable name="level1" select="$currentPage/ancestor-or-self::* [@level = 2]" />  
    <xsl:variable name="level" select="2"/>

    <!-- The fun starts here -->
    <div class="subnav">
      <!-- LEVEL 1 -->
      <xsl:if test="$level1 != ''">
        <a href="{umbraco.library:NiceUrl($level1/@id)}">
          <xsl:if test="$level1/@id = $currentPage/@id">
            <xsl:attribute name="class">current</xsl:attribute>
          </xsl:if>
          <xsl:value-of select="$level1/@nodeName"/>
        </a>
      </xsl:if>
      <!-- LEVEL 2 -->  
      <ul>
        <xsl:for-each select="$currentPage/ancestor-or-self::* [@level=$level]/* [@isDoc and string(umbracoNaviHide) != '1']">
          <xsl:element name="li">
            <xsl:attribute name="class">
              <xsl:if test="$currentPage/ancestor-or-self::*[@isDoc]/@id = current()/@id">
                <xsl:text>current</xsl:text>
              </xsl:if>
            </xsl:attribute>
            <a href="{umbraco.library:NiceUrl(@id)}">
              <xsl:value-of select="@nodeName"/>
            </a>
            <!-- LEVEL 3 if any more nodes are Visible -->
            <xsl:if test="*[@isDoc][not(umbracoNaviHide = 1)]">
              <ul>
                <xsl:for-each select="./* [@isDoc  and string(umbracoNaviHide) != '1']">
                  <xsl:element name="li">
                    <xsl:attribute name="class">
                      <xsl:if test="$currentPage/ancestor-or-self::*[@isDoc]/@id = current()/@id">
                        <xsl:text>current</xsl:text>
                      </xsl:if>
                    </xsl:attribute>
                    <a href="{umbraco.library:NiceUrl(@id)}">
                      <xsl:value-of select="@nodeName" />
                    </a>
                    <!-- LEVEL 4 if any more nodes are Visible -->
                    <xsl:if test="*[@isDoc][not(umbracoNaviHide = 1)]">
                      <ul>
                        <xsl:for-each select="./* [@isDoc  and string(umbracoNaviHide) != '1']">
                          <xsl:element name="li">
                            <xsl:attribute name="class">
                              <xsl:if test="$currentPage/ancestor-or-self::*[@isDoc]/@id = current()/@id">
                                <xsl:text>current</xsl:text>
                              </xsl:if>
                            </xsl:attribute>
                            <a href="{umbraco.library:NiceUrl(@id)}">
                              <xsl:value-of select="@nodeName" />
                            </a>
                          </xsl:element>
                        </xsl:for-each>
                      </ul>
                    </xsl:if>
                  </xsl:element>
                </xsl:for-each>
              </ul>
            </xsl:if>
          </xsl:element>
        </xsl:for-each>
      </ul>
    </div>
    </xsl:template>

    </xsl:stylesheet>
  • Fuji Kusaka 2203 posts 4220 karma points
    May 03, 2012 @ 08:10
    Fuji Kusaka
    1

    Hi JV,

    Good if you got i working. For Unlimited Levels the same thing should be apply. So everytime you will need to run a test to see if any child nodes are available.

     

    //fuji

  • syn-rg 282 posts 425 karma points
    May 03, 2012 @ 09:50
    syn-rg
    0

    Hi Fuji,

    Can you show me an example of how your suggestion would work for unlimited levels?

    Cheers, JV

Please Sign in or register to post replies

Write your reply to:

Draft