Copied to clipboard

Flag this post as spam?

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


  • Daniel Horn 319 posts 344 karma points
    Nov 21, 2010 @ 23:32
    Daniel Horn
    0

    Navigation help

    I need to do this navigation, and i'm messing around with the XSLT, can someone help me out? :)

     

    This is the structure:
    
    Website
    - level1 navi
    -- level2 navi
    --- level3 navi
    --- level3 navi

     

     

            <ul class="undermenu"> 
    
                <li><a href="#">Level2</a>             
    
                    <ul> 
    
                        <li><a href="#" class="aktiv">level3</a></li>                     
    
                        <li><a href="#">Level3</a></li>
    
                    </ul>
    
                </li> 
    
            </ul> 
  • Daniel Horn 319 posts 344 karma points
    Nov 21, 2010 @ 23:33
    Daniel Horn
    0

    Tried to delete the doublepost but wasn't able to..

  • Daniel Horn 319 posts 344 karma points
    Nov 21, 2010 @ 23:53
    Daniel Horn
    0

    Here's the XSLT I have untill now, almost does the trick.. except it doesnt show the last level of navigation :(

     

    <?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"/>

    <xsl:param name="currentPage"/>

    <xsl:variable name="level" select="1"/>
    <xsl:variable name="level2" select="2"/>
    <xsl:variable name="level3" select="3"/>
    <xsl:template match="/">

    <ul class="undermenu">
    <xsl:for-each select="$currentPage/ancestor-or-self::* [@isDoc and @level=$level2]/* [@isDoc and string(umbracoNaviHide) != '1']">
      <li>
        <href="{umbraco.library:NiceUrl(@id)}">
          <xsl:if test="$currentPage/ancestor-or-self::*/@id = current()/@id">
            <!-- This is the active item -->
            <xsl:attribute name="class">aktiv</xsl:attribute>
          </xsl:if>
          <xsl:value-of select="@nodeName"/>
        </a>
        
        
        
        <xsl:for-each select="$currentPage/child::node [@isDoc and @level=$level2]/* [@isDoc and string(umbracoNaviHide) != '1']">
        <ul>
          <li>
          <href="{umbraco.library:NiceUrl(@id)}">
          <xsl:if test="$currentPage/ancestor-or-self::*/@id = current()/@id">
            <!-- This is the active item -->
            <xsl:attribute name="class">aktiv</xsl:attribute>
          </xsl:if>
          <xsl:value-of select="@nodeName"/>
            </a>
          </li>
          
        </ul>
        </xsl:for-each>
        
      </li>
    </xsl:for-each>
    </ul>

    </xsl:template>

    </xsl:stylesheet>
  • Thor Madsen-Holm 82 posts 212 karma points c-trib
    Nov 22, 2010 @ 21:13
    Thor Madsen-Holm
    0

    Looks like you are using the $level2 variable in both of your for-each loops.
    If you use variable $level3 in the 'inner' for-each loop i think it should work.

    Try changing 'inner' for-each loop to this:

    <xsl:for-each select="$currentPage/child::* [@isDoc and @level=$level3]/* [@isDoc and string(umbracoNaviHide) != '1']">

    /Thor

     

     

  • Jan Skovgaard 11280 posts 23678 karma points MVP 10x admin c-trib
    Nov 22, 2010 @ 21:50
    Jan Skovgaard
    0

    Hi Daniel

    Perhaps you can benefit from using the "sitemap" snippet, as it does what you're trying to achieve recursively. There's no need for the $level variables.

    In the sample you can specify the max level...think that is the way to go for you.

    /Jan

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Nov 22, 2010 @ 23:11
    Chriztian Steinmeier
    2

    Hi Daniel (+others)

    Since you all know my position on these matters, I would recommend trying this approach instead - I'm seeing way too much duplication already :-)

    <?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 = 1]" />
    
        <xsl:template match="/">
            <ul class="undermenu">
                <!-- Start with children of the site root -->
                <xsl:apply-templates select="$siteRoot/*[@isDoc]" />
            </ul>
        </xsl:template>
    
        <xsl:template match="*[@isDoc]">
            <li>
                <a href="{umb:NiceUrl(@id)}">
                    <xsl:if test="$currentPage/ancestor-or-self::*[@id = current()/@id]">
                        <xsl:attribute name="class">aktiv</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="*[@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

  • Daniel Horn 319 posts 344 karma points
    Nov 23, 2010 @ 10:52
    Daniel Horn
    0

    Thanks Chriztian, will try it out ! :)

    I really have to spend some time with apply templates etc, it really does make a lot of sense :)

  • PRK 47 posts 119 karma points
    Nov 23, 2010 @ 11:29
    PRK
    0

    Hi Daniel,

     

    check this code. I`ve the same problems when I start with the new schema.

    <?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="/">
      
        <!-- Root Node -->
        <xsl:variable name="rootNode" select="$currentPage/ancestor-or-self::root" />

        <!-- Homepage -->
        <xsl:variable name="homeNode" select="$rootNode/Home [@isDoc]" />
        
        <ul>
          <li>
            <xsl:if test="$homeNode/@id = $currentPage/@id">
              <xsl:attribute name="class">
                <xsl:text>visited</xsl:text>
              </xsl:attribute>
            </xsl:if>
            
            <a href="{umbraco.library:NiceUrl($homeNode/@id)}">
              <xsl:value-of select="$homeNode/@nodeName" />
            </a>
          </li>
          
          <xsl:for-each select="$homeNode/* [@isDoc and @level = 2 and string(umbracoNaviHide) != '1']">
            <li>
              <xsl:if test="$currentPage/ancestor-or-self::* [@isDoc]/@id = current()/@id">
                <xsl:attribute name="class">
                  <xsl:text>visited</xsl:text>
                </xsl:attribute>
              </xsl:if>
              
              <a href="{umbraco.library:NiceUrl(@id)}">
                <xsl:value-of select="@nodeName" />
              </a>
              
              <xsl:variable name="subItems" select="umbraco.library:GetXmlNodeById(@id)/child::* [@isDoc][string(umbracoNaviHide) != '1']"/>
                <xsl:if test="count($subItems)">
                  <table><tr><td>
                    <ul>
                      <xsl:for-each select="$subItems">
                        <li>
                          <a href="{umbraco.library:NiceUrl(@id)}">
                            <xsl:value-of select="@nodeName"/>
                          </a>
                        </li>
                      </xsl:for-each>
                   </ul>
                  </td></tr></table>
                </xsl:if>
              
              <xsl:variable name="subsubItems" select="$subItems/descendant-or-self::* [@isDoc and @level = 4 and string(umbracoNaviHide) != '1']"/>
                <xsl:if test="count($subsubItems)">
                  <table><tr><td>
                    <ul>
                      <xsl:for-each select="$subsubItems">
                        <li>
                          <a href="{umbraco.library:NiceUrl(@id)}">
                            <xsl:value-of select="@nodeName"/>
                          </a>
                        </li>
                      </xsl:for-each>
                   </ul>
                  </td></tr></table>
                </xsl:if>
              
            </li>
          </xsl:for-each>
        </ul>
      </xsl:template>
    </xsl:stylesheet>

     

     

    /PRK

     

  • Daniel Horn 319 posts 344 karma points
    Nov 24, 2010 @ 13:10
    Daniel Horn
    0

    Thanks for all the help guys, I ended up using Chriztians example :), works like a knife through melted butter...

    Chriztian I owe you a beer @ Codegarden :)

  • Daniel Horn 319 posts 344 karma points
    Nov 24, 2010 @ 15:33
    Daniel Horn
    0

    @Chriztian in your above code, how would you put the class="aktiv" on the <li> which is active instead of on the <a> ?

  • Kim Andersen 1447 posts 2196 karma points MVP
    Nov 24, 2010 @ 15:38
    Kim Andersen
    2

    Hi Daniel

    If you want to put the class on the <li> instead of the a you can just do like this:

    <xsl:template match="*[@isDoc]">
             
    <li>
    <xsl:if test="$currentPage/ancestor-or-self::*[@id = current()/@id]">
                         
    <xsl:attribute name="class">aktiv</xsl:attribute>
                 
    </xsl:if>

                  <a href="{umb:NiceUrl(@id)}">
                     
    <xsl:value-of select="@nodeName" />
                 
    </a>
    ...
    ...            

    /Kim A

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Nov 24, 2010 @ 15:40
    Chriztian Steinmeier
    1

    - Just move the three lines (<xsl:if> <xsl:attribute>... </xsl:if>) up right after the <li>: 

    <li>
        <xsl:if test="$currentPage/ancestor-or-self::*[@id = current()/@id]">
            <xsl:attribute name="class">aktiv</xsl:attribute>
        </xsl:if>
            <a href="{umb:NiceUrl(@id)}">
                <xsl:value-of select="@nodeName" />
            </a>

    /Chriztian

  • Daniel Horn 319 posts 344 karma points
    Nov 24, 2010 @ 15:43
    Daniel Horn
    0

    Thanks Chriztian :)

  • Sam 184 posts 209 karma points
    Apr 16, 2011 @ 17:09
    Sam
    0

    Hi everyone,

    I am trying to adapt the above (thanks Chriztian!), so that the menu has a title in the form of

    <li class="menuHeader">Browse sections</li>

    However, when I put this into the code, the 'Browse sections' either shows:

    a) On ALL pages even with no sub pages so a menu title with no menu OR

    b) In between all <li> elements so 'Browse sections' repeats down the menu.

    I can't figure out a test which would mean this title only shows once, above the menu, but only if the menu is present.

    Any help is always appreciated :) thanks.

    Sam.

  • Sam 184 posts 209 karma points
    Apr 16, 2011 @ 17:24
    Sam
    0

    I can expand, I get either:

      <ul class="subMenuLv2">
    <li class="menuHeader">Browse sections</li>
    <li>
    <a href="/about-us/page1.aspx">About 1</a>
    </li>
    <li>
    <a href="/about-us/page2.aspx">About 2</a>
    </li>
    </ul>

    ...the above is how I want it, however, when clicking on a top level page with no sub pages I get this:

    <ul class="subMenuLv2">
    <li class="menuHeader">Browse sections</li>
    </ul>

    which is no good :(

    I thought maybe I could use count to see if page has child nodes, if it does, then show the 'Browse sections', but that wouldn't work either because the 'Browse sections' would disappear when clicking on 'About 1' or 'About 2' as they have no sub pages.

    Then I thought I could test that (a) has sub pages (so 'Browse sections' would display when on top level page) or (b) has a parent page (ie the node must be a sub level if it has a parent?!)

    However, all my top navigations have a parent (home) so once again 'Browse sections' displays on all pages regardless of whether the page has child nodes. Bit confused here.

    Sam.

     

     

     

     

  • Sam 184 posts 209 karma points
    Apr 16, 2011 @ 18:12
    Sam
    0

    Well my first problem I managed to solve :)... but I really wanted the levels to expand when clicked rather than all levels being displayed all the time, here's what I have so far:

    <?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="subMenuLv2">

                    <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>

                      

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

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

                      </xsl:if>

                    

                            <a href="{umb:NiceUrl(@id)}">

                                    <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="*[@isDoc][not(umbracoNaviHide = 1)]">

                                    <ul class="subMenuLv3">

                                            <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>

    Ideally, when on a top level page, all the level 2 nodes will be displayed. Then, if a user clicks on the level 2 node, then the level 3 ones are displayed. I can get a good result with cog navigation but I am sure this way is better for me because I wont learn a thing just chucking a package in there to do the job.

    Thanks if anyone can help :)

    Sam.

     

     

Please Sign in or register to post replies

Write your reply to:

Draft