Copied to clipboard

Flag this post as spam?

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


  • tc 41 posts 62 karma points
    Sep 23, 2010 @ 11:42
    tc
    0

    Navigation Help

    Hi There,

    I had a sitemap as follows.

    • Home
    • Section 1
    • Page 1
    • Page 2
    • Section 2
    • Page 1
    • Page 2
    • Section 3
    • Page 1
    • Page 2
    And my navigation code was..
    <xsl:for-each select="$currentPage/ancestor-or-self::* [@level=$level]/* [@isDoc and string(umbracoNaviHide) != '1']">

      <!-- Check if link should be active -->  
      <xsl:choose>
      
        <xsl:when test="$currentPage/@id = @id">
        
          <li class="active">
            <href="{umbraco.library:NiceUrl(@id)}">
              <xsl:value-of select="@nodeName"/>
            </a>
          </li>
        
        </xsl:when>
        
        <xsl:otherwise>
        
          <li>
            <href="{umbraco.library:NiceUrl(@id)}">
              <xsl:value-of select="@nodeName"/>
            </a>
          </li>
        
        </xsl:otherwise>
      
      </xsl:choose>

      
    </xsl:for-each>
    Level was set to 2, so when browsing a section, the navigation would display all its children. But, now i want to have a section within a section like so..
    • Home
    • Section 1
    • Page 1
    • Page 2
    • Section1.1
    • Page 1.1
    • Section 2
    • Page 1
    • Page 2
    • Section 3
    • Page 1
    • Page 2
    And the navigation is thrown off, when i click section 1.1 the navigation shows its siblings, instead i want it to show its children, but if i make this change, im still shown its siblings, if i correct it to level 3, im shown its children, but i cant link to its siblings.
    Im just wondering what the best approach is for this
    Thanks

  • dandrayne 1138 posts 2262 karma points
    Sep 23, 2010 @ 11:55
    dandrayne
    0

    Hi Tc

    I'm working on something like this just now, which will write out all the sub-navigation regardless of where the user currently is.  I've added a few comments to the code that should help

    <?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="html" omit-xml-declaration="yes"/>

    <xsl:param name="currentPage"/>

    <!-- update this variable on how deep your site map should be -->
    <xsl:variable name="maxLevelForSitemap" select="6"/>

    <xsl:template match="/">
    <!-- Always start the side navigation at level 2 -->
    <xsl:variable name="parentNode" select="$currentPage/ancestor-or-self::* [@isDoc and @level=2]" />
    <!-- only call the template if the parent node is present and has children -->
    <xsl:if test="string($parentNode/@id) != '' and count($parentNode/* [@isDoc and string(./umbracoNaviHide) != '1']) &gt; 0">
    <xsl:call-template name="drawNodes">
    <xsl:with-param name="parent" select="$parentNode"/>
    </xsl:call-template>
    </xsl:if>
    </xsl:template>

    <xsl:template name="drawNodes">
    <xsl:param name="parent"/>
    <!-- check to see if this page isn't hidden, or if it is hidden that the user is logged on -->
    <xsl:if test="umbraco.library:IsProtected($parent/@id, $parent/@path) = 0 or (umbraco.library:IsProtected($parent/@id, $parent/@path) = 1 and umbraco.library:IsLoggedOn() = 1)">
    <ul class="subnav">
    <!-- for each child page that isn't hidden or one of our node types that we don't to show -->
    <xsl:for-each select="$parent/* [@isDoc and string(./umbracoNaviHide) != '1' and @level &lt;= $maxLevelForSitemap and name()!='NewsItem' and name()!='Event' and name()!='DateFolder']">
    <li>
    <!-- Check if this is on the current path -->
    <xsl:if test="$currentPage/ancestor-or-self::*/@id = current()/@id">
    <xsl:attribute name="class">current</xsl:attribute>
    </xsl:if>
    <a href="{umbraco.library:NiceUrl(@id)}">
    <xsl:value-of select="@nodeName"/></a>
    <!-- If this page has children, call the template recursively to continue writing out the navigation -->
    <xsl:if test=" count(./* [@isDoc and string(./umbracoNaviHide) != '1' and @level &lt;= $maxLevelForSitemap and name()!='NewsItem' and name()!='Event' and name()!='DateFolder']) &gt; 0">
    <xsl:call-template name="drawNodes">
    <xsl:with-param name="parent" select="."/>
    </xsl:call-template>
    </xsl:if>
    </li>
    </xsl:for-each>
    </ul>
    </xsl:if>
    </xsl:template>
    </xsl:stylesheet>

    Dan

  • tc 41 posts 62 karma points
    Sep 23, 2010 @ 13:04
    tc
    0

    Hey, thanks for the speedy reply!
    I havent had chance to test this but will update you when i do.

    Will this be able to cope with displaying children if it is a "section" or displaying its ancestors if it is a "page" similar to my site map above?

    I should get chance to test it soon.

    Thanks again!

  • tc 41 posts 62 karma points
    Sep 23, 2010 @ 13:14
    tc
    0

    Just got round to testing.

    With this xslt, the navigation for section1, shows links to page 1, page 2 and section 1.1 which is good, but it also shows the link to page1.1 which should only be visible from the section 1.1 navigation (if this makes sense). If the node is a "Section" i want to display its children, if it is a "Page" i want to display its siblings. Is this possible?

    Thanks again!

  • dandrayne 1138 posts 2262 karma points
    Sep 23, 2010 @ 13:51
    dandrayne
    0

    Could this be solved with CSS?

    ul.subnav ul {dislay: none;}
    ul.subnav li.current ul {display:block;}

    Or do you not want to show the link to section 2, section 3 etc if you're inside section 1? 

    Dan

  • tc 41 posts 62 karma points
    Sep 24, 2010 @ 10:51
    tc
    0

    Hi, yeah i dont want to show the link to section 2 or section 3 from section 1. Ill describe it as best i can...

    From home, the navigation should consist of "Section 1, Section 2, Section3".
    On clicking one of these links, the user decends into the section. Once in a section, the navigation changes to display children of that section. So, assuming the user navigates to section 1, the navigation would be "Page 1, Page 2, Section 1.1". Now, if the user is viewing a page, the navigation doesnt need to change, or rather, it should display the pages siblings. So, if the user views page 1, the navigation would still be "Page 1(active link), Page 2, Section 1.1". If the user navigates to section 1.1, the navigation should change and show the children of this section, this should be "Page 1.1"

     

    Thanks again!

  • dandrayne 1138 posts 2262 karma points
    Sep 24, 2010 @ 11:15
    dandrayne
    0

    Sorry for being a bit slow here!  I'm still not 100% sure of the requirement, but I think you might be able to get this by changing the parentNode variable depending on where you are in the tree, so if you're at a level 3 page start the subnav at level 3 etc instead of level 2.

    Something along these lines/

     

    <xsl:variable name="parentNode">
        <xsl:choose>
            <xsl:when test="$currentPage/@level &lt; 3">
                <xsl:value-of select="$currentPage/ancestor-or-self::* [@isDoc and @level=2]" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$currentPage/ancestor-or-self::* [@isDoc and @level=3]" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>   
    

    Note - the above code might not do what you need, but perhaps by playing with setting the initial parent node you can get the outcome you're after.

    Dan

     

     

  • tc 41 posts 62 karma points
    Sep 27, 2010 @ 09:51
    tc
    0

    Hi again,

    Im still not having much luck with this, how do i go about using that piece of code you put? I thought i could just use

    <xsl:for-each select="$parentNode">

    but for some reason its not letting me do that and gives an error asking me to convert to node-set();

     

  • Rich Green 2246 posts 4008 karma points
    Sep 27, 2010 @ 10:47
    Rich Green
    0

    You would have to use this code

    <xsl:for-each select="umbraco.library.GetXmlNodeByID($parentNode)">
    
    </xsl:for-each> 

    Rich

  • tc 41 posts 62 karma points
    Sep 27, 2010 @ 15:15
    tc
    0

    Hi Rich, i used the code you put above and got the gfollowing error

     

    umbraco.library.GetXmlNodeById()' is an unknown XSLT function

  • Rich Green 2246 posts 4008 karma points
    Sep 27, 2010 @ 15:17
    Rich Green
    0

    Sorry, typo. Try this:

    <xsl:for-each select="umbraco.library:GetXmlNodeById($parentNode)">
    
    </xsl:for-each>

    Rich

  • tc 41 posts 62 karma points
    Sep 27, 2010 @ 15:35
    tc
    0

    Yeah just noticed it should be a ":"
    still no luck tho, i dont get any menu rendered then,

    I thought that the $parentNode variable actually contains a set, because its gets the current nodes ancestors and itself, which is why it makes sense that i get the following error.. how do i select the first from this set? is that even the right one?

     "To use a result tree fragment in a path expression, first convert it to a node-set using the msxsl:node-set() function. "

  • dandrayne 1138 posts 2262 karma points
    Sep 27, 2010 @ 15:39
    dandrayne
    0

    Hi tc

    To use GetXmlNodeById we need to save an integer id instead of the node.  So instead of 

     

    <xsl:variable name="parentNode">
           
    <xsl:choose>
                   
    <xsl:when test="$currentPage/@level &lt; 3">
                           
    <xsl:value-of select="$currentPage/ancestor-or-self::* [@isDoc and @level=2]" />
                   
    </xsl:when>
                   
    <xsl:otherwise>
                           
    <xsl:value-of select="$currentPage/ancestor-or-self::* [@isDoc and @level=3]" />
                   
    </xsl:otherwise>
           
    </xsl:choose>
    </xsl:variable>

     

    You'd use this

    <xsl:variable name="parentNode">
            <xsl:choose>
                    <xsl:when test="$currentPage/@level &lt; 3">
                            <xsl:value-of select="$currentPage/ancestor-or-self::* [@isDoc and @level=2]/@id" />
                    </xsl:when>
                    <xsl:otherwise>
                            <xsl:value-of select="$currentPage/ancestor-or-self::* [@isDoc and @level=3]/@id" />
                    </xsl:otherwise>
            </xsl:choose>
    </xsl:variable> 

    Then you can use

    umbraco.library:GetXmlNodeById($parentNode)

    Hope this helps,

    Dan

  • tc 41 posts 62 karma points
    Sep 27, 2010 @ 15:44
    tc
    0

    Hi Dan,
    that saved properly, thanks.

    Im still having trouble. As far as i am aware, the $parentNode should now contain the node for which children to get, so i try and loop through them. However, i still get no menu selected. I know $parentNode is set, as if i just use that in the for each, it renders a link to itself. Yet for some reason, if i try and access its children, i get no menu displayed.

    Below is the code im using.

    I get the parent ndoe, then loop through its children and render a list, theres a little choose statement in there just to determin whether to highlight the current link.

     

    <xsl:variable name="parentNode">
            <xsl:choose>
                    <xsl:when test="$currentPage/@level &lt; 3">
                            <xsl:value-of select="$currentPage/ancestor-or-self::* [@isDoc and @level=2]/@id" />
                    </xsl:when>
                    <xsl:otherwise>
                            <xsl:value-of select="$currentPage/ancestor-or-self::* [@isDoc and @level=3]/@id" />
                    </xsl:otherwise>
            </xsl:choose>
    </xsl:variable

    <xsl:template match="/">
      
    <!-- The fun starts here -->
      <xsl:if test="$parentNode > 0" >
        <xsl:for-each select="umbraco.library:GetXmlNodeById($parentNode)/*">
      
      <!-- Check if link should be active -->
      <xsl:choose>
      
        <xsl:when test="$currentPage/@id = @id">
        
          <li class="active">
            <href="{umbraco.library:NiceUrl(@id)}">
              <xsl:value-of select="@nodeName"/>
            </a>
          </li>
        
        </xsl:when>
        
        <xsl:otherwise>
        
          <li>
            <href="{umbraco.library:NiceUrl(@id)}">
              <xsl:value-of select="@nodeName"/>
            </a>
          </li>
        
        </xsl:otherwise>
      
      </xsl:choose>
      
    </xsl:for-each>
      </xsl:if>
    </xsl:template>
  • tc 41 posts 62 karma points
    Sep 27, 2010 @ 15:56
    tc
    0

    OKay, im makign progress here

    i used the following code to set the level variable

    <xsl:variable name="level">
      <xsl:choose>
          <xsl:when test="$currentPage/@level &lt; 3">
            <xsl:text>2</xsl:text>
          </xsl:when>
          <xsl:otherwise>
            <xsl:text>3</xsl:text>
          </xsl:otherwise>
      </xsl:choose>
    </xsl:variable

    And im getting a navigation rendered, i can look at section 1 and it will show page 1, 2, 3 and section 1.1, i can choose section 1.1 and it will show me page 1.1. However, if i am in section 1 and choose page 1, 2, or 3, the navigation just dissapears. (Also, i know hard coding levels 2, and 3 like above wont cope well with expansion, its just a test for now.

     

    Thanks

  • tc 41 posts 62 karma points
    Sep 27, 2010 @ 16:09
    tc
    0

    Okay, i seem to have got somewhere,

    What i did was decrement the level if this page is not a section.

    <xsl:variable name="level">
      <xsl:choose>
          <xsl:when test="$currentPage/@nodeName = 'Home'">
            <xsl:text>0</xsl:text>
          </xsl:when>
          <xsl:when test="$currentPage/@nodeType = 1135">
            <xsl:value-of select="$currentPage/@level" />
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$currentPage/@level - 1" />
          </xsl:otherwise>
      </xsl:choose>
    </xsl:variable

     

    Im nto entirely sure why decrementing the level if the page is not a section works, as i originally thought incrementing it if it was a section, and keepign it the same if it was a page would work, so this took some trial and error. If anyone has a better method, or could even shed a little light on how this actually worked then i would be greatful! :)

     

    Thanks!

Please Sign in or register to post replies

Write your reply to:

Draft