Here is an example of how you can achieve that. Basically you loop through a template for each item, checking if there are children and,if there are, nesting these and checking them for children.
<xsl:param name="currentPage"/>
<!-- stop loop at level: --> <xsl:variable name="maxLevel" select="3" /> <xsl:template match="/"> <div id="nav"> <xsl:call-template name="drawNodes"> <xsl:with-param name="parent" select="$currentPage/ancestor-or-self::* [@isDoc and @level=1]"/> </xsl:call-template> </div> </xsl:template> <xsl:template name="drawNodes"> <xsl:param name="parent"/> <xsl:if test="$parent/@level < $maxLevel"> <ul id="secondaryNavigation"> <xsl:for-each select="$parent/* [@isDoc and string(umbracoNaviHide) != '1']"> <li> <a href="{umbraco.library:NiceUrl(@id)}"> <xsl:value-of select="@nodeName" /> </a> <!-- check if there is another level - if so run through again --> <xsl:if test="count(./* [@isDoc and string(umbracoNaviHide) != '1']) > 0 and $currentPage/ancestor-or-self::*/@id = current()/@id"> <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>
I hope that helps point you in the right direction! Shout if it doesn't :)
<xsl:param name="currentPage"/> <!-- stop loop at level: --> <xsl:variable name="maxLevel" select="3" /> <xsl:template match="/"> <ul id="nav"> <xsl:call-template name="drawNodes"> <xsl:with-param name="parent" select="$currentPage/ancestor-or-self::* [@isDoc and @level=1]"/> </xsl:call-template> </ul> </xsl:template> <xsl:template name="drawNodes"> <xsl:param name="parent"/> <xsl:if test="$parent/@level < $maxLevel"> <!--<ul>--> <xsl:for-each select="$parent/* [@isDoc and string(umbracoNaviHide) != '1']"> <li> <a href="{umbraco.library:NiceUrl(@id)}"> <xsl:value-of select="@nodeName" /> </a>
</li> <!-- check if this is the current page AND if this has a child - if so run through again --> <xsl:if test="count(./* [@isDoc and string(umbracoNaviHide) != '1']) > 0 and $currentPage/ancestor-or-self::*/@id = current()/@id"> <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>
Just changed the wrapper to a ul, removed the ul in the drawNodes template and stopped the redraw being nested in a li. Personally I would keep the nested ul since it shows a logical relationship of child to parent and helps if you need distinct styling
Sorry this isn't working for you - what is being returned? If you are just getting an empty ul try increasing the maxLevel variable. This stops pages being output based on how deep in the site structure they are.
Its working now....one little thing can you tell me how can I get the 3 level to have a padding:left:10px; to make it look different from the its 2nd leve parent
<xsl:variable name="maxLevel" select="4" /> <xsl:template match="/"> <ul class="subNav_inter"> <li id="ancestor"> <a > <xsl:attribute name="href"> <xsl:value-of select="umbraco.library:NiceUrl($currentPage/ancestor-or-self::* [@isDoc and @level = 2]/@id)"/></xsl:attribute> <xsl:value-of select="$currentPage/ancestor-or-self::* [@isDoc and @level = 2]/@nodeName"/> </a> </li> <xsl:call-template name="drawNodes"> <xsl:with-param name="parent" select="$currentPage/ancestor-or-self::* [@isDoc and @level=2]"/> </xsl:call-template> </ul> </xsl:template> <xsl:template name="drawNodes"> <xsl:param name="parent"/> <xsl:if test="$parent/@level < $maxLevel"> <!--<ul>--> <xsl:for-each select="$parent/* [@isDoc and string(umbracoNaviHide) != '1']"> <li> <xsl:if test="$currentPage/self::*[@isDoc]/@id = current()/@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> <!-- check if this is the current page AND if this has a child - if so run through again --> <xsl:if test="count(./* [@isDoc and string(umbracoNaviHide) != '1']) > 0 and $currentPage/ancestor-or-self::*/@id = current()/@id"> <xsl:call-template name="drawNodes"> <xsl:with-param name="parent" select="."/> </xsl:call-template> </xsl:if> <!--</li>--> </xsl:for-each> <!--</ul>--> </xsl:if>
Note this example will only add the padding to level 3 items. If you need to keep incrementing the padding based on level you could pass another parameter - let me know if you want to pursue this.
Personally I'd go with the classes option since it's cleaner and gives more flexibility, but I know this isn't always an option.
Looks to be checking that the current li has an ancestor which has a position of 4 ($maxLevel). If you are wanting to check the level you should have [@level = $maxLevel]. Additionally this attribute will overwrite the previous so you can't have an li with a class of 'current ancestor-of'. If for whatever reason you need this just use a single attribute declaration and nest the conditions inside. This will result in some empty class attributes being output (i.e. where the li is neither current nor ancestor-of) although there are ways around that.
May be you can help me out with this....i want to achieve something like class="ancestor current" for the ancestor to hav another color when being active.
Right so it seems to me that the test you are using to apply a class of 'tit' will always return true. So this class is always added. However the 'ancestor' test only fires a few times and this overwrites the 'tit' class, which is why you get the varied result. I'm not sure how far you navigation progresses and I've tried to keep the functionality you are currently experiencing. Try this code below:
May be you can help me out with that. Am having another navigation issue this time under V4.7.
Here is the situation
what am trying to achieve is to display all the nodes from Folder 2 even the sub sub links. But am only getting the sublinks so far with the following code and using ListSubPagesFromChangeableSource XSLT. Those nodes needs to be present on all my pages.
<!-- The fun starts here --> <ul> <xsl:call-template name="drawNodes"> <xsl:with-param name="parent" select="umbraco.library:GetXmlNodeById($source)/* [@isDoc and string(umbracoNaviHide) != '1']"/> </xsl:call-template> </ul> </xsl:template>
<!-- The fun starts here --> <ul> <xsl:call-template name="drawNodes"> <xsl:with-param name="parent" select="umbraco.library:GetXmlNodeById($source)/* [@isDoc and string(umbracoNaviHide) != '1']"/> </xsl:call-template> </ul> </xsl:template>
<!-- The fun starts here --> <ul> <xsl:call-template name="drawNodes"> <xsl:with-param name="parent" select="umbraco.library:GetXmlNodeById($source)/* [@isDoc and string(umbracoNaviHide) != '1']"/> </xsl:call-template> </ul> </xsl:template>
Displaying sub Pages
HI,
I have this following structure in my website
- Content
-- Default
--- Page 1
---- Sub Page 1
-----> Inner Sub Page 1
-----> Inner Sub Page 2
---- Sub Page 2
So bascially i have a 3level side navigation.....what am trying to do is when i click on Page 1, I the following display
--- Page 1
---- Sub Page 1
---- Sub Page 2
Which is working fine
But when i click on ---- Sub Page 1 i want the following display
--- Page 1
---- Sub Page 1
-----> Inner Sub Page 1
-----> Inner Sub Page 2
---- Sub Page 2
But am getting the wrong display atm, its displaying
--- Page 1
---- Sub Page 1
---- Sub Page 2
-----> Inner Sub Page 1
-----> Inner Sub Page 2
Where my Inner Sub Pages show be underneath Sub Page 1 instead
Can someon tell me where is was wrong in my following code??
The trouble is that you are output the code in that order:
All level 1 items
All level 2 items
All level 3 items
I always nest lists for navigation so that you can see the parent to child relationship. Typical code out put would be:
with anchor tags as well though :)
Here is an example of how you can achieve that. Basically you loop through a template for each item, checking if there are children and,if there are, nesting these and checking them for children.
I hope that helps point you in the right direction! Shout if it doesn't :)
HI Stuart,
Thanks for the reply.....i got lost somehow at some point with my xslt, on this project i have like 4 different sub navigation!!
Well my output should be
Just changed the wrapper to a ul, removed the ul in the drawNodes template and stopped the redraw being nested in a li. Personally I would keep the nested ul since it shows a logical relationship of child to parent and helps if you need distinct styling
Hope that works for you :)
Hi Stuart,
Thanks again but its not working am working on
Hi Fuji,
Sorry this isn't working for you - what is being returned? If you are just getting an empty ul try increasing the maxLevel variable. This stops pages being output based on how deep in the site structure they are.
Stuart,
Its working now....one little thing can you tell me how can I get the 3 level to have a padding:left:10px; to make it look different from the its 2nd leve parent
//fuji
Great!
I'd style using classes and so would add an attribute to the li. For example replace the li above with this:
If you want to do this with inline styles wrap it in a condition. Example:
Note this example will only add the padding to level 3 items. If you need to keep incrementing the padding based on level you could pass another parameter - let me know if you want to pursue this.
Personally I'd go with the classes option since it's cleaner and gives more flexibility, but I know this isn't always an option.
Thanks for the help Stuart,
Here is how i did it the other way round....
Glad this is working for you :)
Just to check, what is this supposed to do:
Looks to be checking that the current li has an ancestor which has a position of 4 ($maxLevel). If you are wanting to check the level you should have [@level = $maxLevel]. Additionally this attribute will overwrite the previous so you can't have an li with a class of 'current ancestor-of'. If for whatever reason you need this just use a single attribute declaration and nest the conditions inside. This will result in some empty class attributes being output (i.e. where the li is neither current nor ancestor-of) although there are ways around that.
Sorry I went on a bit there! :D
Thanks man...
Fuji
Stuart,
May be you can help me out with this....i want to achieve something like class="ancestor current" for the ancestor to hav another color when being active.
//fuji
Try changing this:
To this:
My ancestor-of is not displaying anything however.....
oh, i see what I did. I've mixed up my conditions. In the last post where you added code you had a condition for 'ancestor-of' of:
$parent/ancestor-or-self::* [$maxLevel]
I've included that in my wrapping test but changed it in my inner test - these should match, just use whatever test you have currently in your code
Here is how i did this part
And my output is the following
<ul>
<li class="tit"><a href="#">TITLE 1</a></li>
<li class="ancestor"><a href="#">Sub Page 1</a></li>
<li class="ancestor"><a href="#">Sub Page 2 </a></li>
<li class="ancestor"><a href="#">Sub Page 3</a></li>
<li class="tit"><a href="#">TITLE 2</a></li>
<li class="tit"><a href="#">TITLE 3</a></li>
<li class="tit"><a href="#">TITLE 4</a></li>
</ul>
But instead i would like to get an active class when am on SubPage 1
<ul>
<li class="tit"><a href="#">TITLE 1</a></li>
<li class="ancestor current"><a href="#">Sub Page 1</a></li>
<li class="ancestor"><a href="#">Sub Page 2 </a></li>
<li class="ancestor"><a href="#">Sub Page 3</a></li>
<li class="tit"><a href="#">TITLE 2</a></li>
<li class="tit"><a href="#">TITLE 3</a></li>
<li class="tit"><a href="#">TITLE 4</a></li>
</ul>
//fuji
Right so it seems to me that the test you are using to apply a class of 'tit' will always return true. So this class is always added. However the 'ancestor' test only fires a few times and this overwrites the 'tit' class, which is why you get the varied result. I'm not sure how far you navigation progresses and I've tried to keep the functionality you are currently experiencing. Try this code below:
Hi Stuart,
Am back to work!!! yes let me try this out...
//fuji
Staurt,
Its working, it just needed some changes here is how i got it working since the max level for me is actually Level = 2.
Thanks again....btw will you be at CG11?
No worries man, glad it's working for you :)
Unfortuantely not going to CG11... hopefully next year though - sounds like a blast!
Hi Stuart,
May be you can help me out with that. Am having another navigation issue this time under V4.7.
Here is the situation
what am trying to achieve is to display all the nodes from Folder 2 even the sub sub links. But am only getting the sublinks so far with the following code and using ListSubPagesFromChangeableSource XSLT. Those nodes needs to be present on all my pages.
//fuji
Hi again,
Try removing:
and $currentPage/ancestor-or-self::*/@id = current()/@id
I'm not sure what this is being used for and the rest of the code seems fine...
Hi stuart,
Try removing which part??
All that text I pasted. Here it is again not in a code block "and $currentPage/ancestor-or-self::*/@id = current()/@id"
I Changed this
to
But still displaying only the sub nodes
is working on a reply...