I am fairly new to xslt and Umbraco. I have been trying to achieve the following xslt navigation for a few days without success.
I have a Main Nav on the left and Sub nav below it. like so
main nav:
Home - Level 1 About Us - Level 2 News- Level 2 Contact- Level 2
Sub Nav Who are we- Level 3 What we do- Level 3 How we do it- Level 3
The node structure on the Contents panel of admin site is as follows
-Home --About Us ---Who are we ---What we do ---How we do it --News ---News 1 ---News 2 --Contact
Problem My problem is that I am trying to hide the sub menu is there are no child nodes in the Level 2 Menu. If however there are child nodes are present in then the Sub menu should be shown. I have got it working to the tune that the sub menu is shown and loaded with child content but I cannot seem to hide it if there are no child nodes. The sub menu should still be shown when say the user click on the "What we do" link in the sub menu.
Ok, so based on what you are saying here are some thoughts. In order to always show this menu no matter where you are in the site you will need to go with either GetXmlAll, GetXmlByNodeId, or traverse the tree using the ancestor-or-self axes.
One approach might be somehting like this:
<ul> <xsl:for-each select="$currentPage/ancestor-or-self::node [@level=2 and string(data [@alias='umbracoNaviHide']) != '1']"> <li> <a href="{umbraco.library:NiceUrl(@id)}"> <xsl:value-of select="@nodeName"/> </a> <!-- get the sub items (children only) of the current node (NOTE: i am speclling ut the axes here, but that is not necessary) --> <xsl:variable name="subItems" select="umbraco.library:GetXmlNodeById(@id)/child::node [string(data [@alias='umbracoNaviHide']) != '1']"/> <xsl:if test="count($subItems)"> <ul class="sub-nav"> <xsl:for-each select="$subItems"> <li> [sub] <xsl:value-of select="@nodeName"/> </li> </xsl:for-each> </ul> </xsl:if> </li> </xsl:for-each> </ul>
<li> <!-- Add the class selected if the root node ID matches our current node ID in the for each loop --> <xsl:if test="$rootNode/@id = $currentPage/@id"> <xsl:attribute name="class"> <xsl:text> selected </xsl:text> </xsl:attribute> </xsl:if>
<xsl:for-each select="$currentPage/ancestor-or-self::node/node [@level = 2 and string(data[@alias='umbracoNaviHide']) != '1']"> <li> <!-- Add the class selected if the currentpage or parent nodes (up the tree to the root) ID matches our current node ID in the for each loop --> <xsl:if test="$currentPage/ancestor-or-self::node/@id = current()/@id"> <xsl:attribute name="class"> <xsl:text> selected </xsl:text> </xsl:attribute>
<!-- Input the documenttype you want here --> <!-- Typically '1' for topnavigtaion and '2' for 2nd level --> <!-- Use div elements around this macro combined with css --> <!-- for styling the navigation --> <xsl:variable name="level" select="2"/> <xsl:variable name="minLevel" select="1"/> <xsl:template match="/">
<!-- The fun starts here --> <xsl:if test="count($currentPage/parent::node [string(data [@alias='umbracoNaviHide']) != '1']) > 0"> <!-- Problem Area --> <table cellpadding="0" cellspacing="0" border="1"> <tr> <td class="subMenuHeader"><div class="subMenuHeaderText"><xsl:value-of select="$currentPage/@nodeName"/></div></td> </tr> <tr> <td class="subMenuContents"> <ul> <xsl:for-each select="$currentPage/ancestor-or-self::node [@level=$level]/node [string(data [@alias='umbracoNaviHide']) != '1']"> <li> <a href="{umbraco.library:NiceUrl(@id)}"> <xsl:if test="$currentPage/ancestor-or-self::node/@id = current()/@id"> <!-- we're under the item - you can do your own styling here --> <xsl:attribute name="style">font-weight: bold;</xsl:attribute> </xsl:if> <xsl:value-of select="@nodeName"/>--<xsl:value-of select="data [@alias='umbracoNaviHide']" /> </a> </li> </xsl:for-each> </ul> </td> </tr> <tr> <td class="subMenuFooter"></td> </tr> </table> </xsl:if> </xsl:template>
xslt and sub menu
Hi All
I am fairly new to xslt and Umbraco. I have been trying to achieve the following xslt navigation for a few days without success.
I have a Main Nav on the left and Sub nav below it. like so
main nav:
Home - Level 1
About Us - Level 2
News- Level 2
Contact- Level 2
Sub Nav
Who are we- Level 3
What we do- Level 3
How we do it- Level 3
The node structure on the Contents panel of admin site is as follows
-Home
--About Us
---Who are we
---What we do
---How we do it
--News
---News 1
---News 2
--Contact
Problem
My problem is that I am trying to hide the sub menu is there are no child nodes in the Level 2 Menu. If however there are child nodes are present in then the Sub menu should be shown. I have got it working to the tune that the sub menu is shown and loaded with child content but I cannot seem to hide it if there are no child nodes.
The sub menu should still be shown when say the user click on the "What we do" link in the sub menu.
Hope this helps.
Any help would be appreciated
Thanks
Sailr
If you post the XSLT that you got so far it will be much easier for us to help you.
Also, have you seen this project: http://our.umbraco.org/projects/cogworks---flexible-navigation
I do not know if it does exactly what you want but it migth be helpful.
Could you post the code? It's always easier to see what's going on if there's code to look at.
/Thomas Kahn
Ok, so based on what you are saying here are some thoughts. In order to always show this menu no matter where you are in the site you will need to go with either GetXmlAll, GetXmlByNodeId, or traverse the tree using the ancestor-or-self axes.
One approach might be somehting like this:
Hope this helps.
Cheers,
Nik
I have the menu as follows. Its in two parts. This is because it is not nested.
Main menu
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>
<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"
exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets ">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:param name="currentPage"/>
<xsl:template match="/">
<ul class="mainnav">
<xsl:variable name="rootNode" select="$currentPage/ancestor-or-self::node [@level=1]" />
<li>
<!--
Add the class selected if the root node ID matches our
current node ID in the for each loop
-->
<xsl:if test="$rootNode/@id = $currentPage/@id">
<xsl:attribute name="class">
<xsl:text>
selected
</xsl:text>
</xsl:attribute>
</xsl:if>
<a href="{umbraco.library:NiceUrl($rootNode/@id)}">
<xsl:value-of select="$rootNode/@nodeName" />
</a>
</li>
<xsl:for-each select="$currentPage/ancestor-or-self::node/node [@level = 2 and string(data[@alias='umbracoNaviHide']) != '1']">
<li>
<!--
Add the class selected if the currentpage or parent nodes (up the tree to the root)
ID matches our current node ID in the for each loop
-->
<xsl:if test="$currentPage/ancestor-or-self::node/@id = current()/@id">
<xsl:attribute name="class">
<xsl:text>
selected
</xsl:text>
</xsl:attribute>
</xsl:if>
<a href="{umbraco.library:NiceUrl(@id)}">
<xsl:value-of select="@nodeName" />
</a>
</li>
</xsl:for-each>
</ul>
</xsl:stylesheet>
Sub Menu
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>
<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"
exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets ">
<xsl:output method="xml" omit-xml-declaration="yes" />
<xsl:param name="currentPage"/>
<!-- Input the documenttype you want here -->
<!-- Typically '1' for topnavigtaion and '2' for 2nd level -->
<!-- Use div elements around this macro combined with css -->
<!-- for styling the navigation -->
<xsl:variable name="level" select="2"/>
<xsl:variable name="minLevel" select="1"/>
<xsl:template match="/">
<!-- The fun starts here -->
<xsl:if test="count($currentPage/parent::node [string(data [@alias='umbracoNaviHide']) != '1']) > 0"> <!-- Problem Area -->
<table cellpadding="0" cellspacing="0" border="1">
<tr>
<td class="subMenuHeader"><div class="subMenuHeaderText"><xsl:value-of select="$currentPage/@nodeName"/></div></td>
</tr>
<tr>
<td class="subMenuContents">
<ul>
<xsl:for-each select="$currentPage/ancestor-or-self::node [@level=$level]/node [string(data [@alias='umbracoNaviHide']) != '1']">
<li>
<a href="{umbraco.library:NiceUrl(@id)}">
<xsl:if test="$currentPage/ancestor-or-self::node/@id = current()/@id">
<!-- we're under the item - you can do your own styling here -->
<xsl:attribute name="style">font-weight: bold;</xsl:attribute>
</xsl:if>
<xsl:value-of select="@nodeName"/>--<xsl:value-of select="data [@alias='umbracoNaviHide']" />
</a>
</li>
</xsl:for-each>
</ul>
</td>
</tr>
<tr>
<td class="subMenuFooter"></td>
</tr>
</table>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
I've just had a quick look, but here's an idea. In you sub menu xslt try replacing:
<xsl:if test="count($currentPage/parent::node [string(data [@alias='umbracoNaviHide']) != '1']) > 0">
with:
<xsl:if test="count($currentPage/parent::node [string(data [@alias='umbracoNaviHide']) != '1' and @level = '3')]) > 0">
Thanks Daniel, that makes the whole Sub Nav disappear even for those with child nodes
Sorry should be:
<xsl:if test="count($currentPage/parent::node [string(data [@alias='umbracoNaviHide']) != '1' and @level = '3']) > 0">
Or maybe:
<xsl:if test="$currentPage/@level >= 3 or count($currentPage/child::node [string(data [@alias='umbracoNaviHide']) != '1' and @level = '3']) > 0">
You are a star !!! works like a charm.
Thanks.
Sailesh
is working on a reply...