I am am trying to create a "tab" type navigation that will have dropdown links appear on hover, but the top node shouldn't have a link associated with it if it has child nodes (eg; https://edit-www.rose-hulman.edu/offices-services/alumni-affairs-2.aspx). I am using this in my xslt file for the navigation, but as it is if there are grandchild nodes in the navigation that are not "hidden from navigation" then my xslt restricts that inner parent node to not have a link associated with it. Basicly, I don't wan't top level parent nodes to have links associated with them unless they have no subnodes, but I want the ability to have subnodes that link with child nodes as well.
Here is my xslt file:
<xsl:template name="node-link-with-span"> <xsl:param name="node" /> <xsl:if test="string($node) != ''"> <a> <xsl:attribute name="href"> <xsl:choose> <xsl:when test="count($node/* [@isDoc and string(umbracoNaviHide) != '1'])"> <![CDATA[javascript://]]> </xsl:when> <xsl:when test="$node[name() = 'ExternalLink']"> <xsl:value-of select="$node/url" /> </xsl:when> <xsl:otherwise> <xsl:value-of select="umbraco.library:NiceUrl($node/@id)" /> </xsl:otherwise> </xsl:choose> </xsl:attribute> <span> <xsl:call-template name="node-name"> <xsl:with-param name="node" select="$node" /> </xsl:call-template> </span> </a> </xsl:if> </xsl:template> <!-- A template to output the correct name for a given node. Better than copy/pasting this code all over the place --> <xsl:template name="node-name"> <xsl:param name="node" /> <xsl:if test="string($node) != ''"> <xsl:choose> <xsl:when test="$node/pageTitle != ''"> <xsl:value-of select="$node/pageTitle"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$node/@nodeName"/> </xsl:otherwise> </xsl:choose> </xsl:if> </xsl:template>
I'm having a hard time understanding exactly what your problem is - I think part of your problem is in another part of the code (not shown), i.e., the code above doesn't recurse through the sub pages...
Say you have the following content structure - what would be your desired HTML output then?
Home
- Page 1
- Page 2
- - Sub 2.1
- - Sub 2.2
- Page 3
- - Sub 3.1 (hidden)
- - - Gran 3.1.1
- Page 4
PS: Navigations are a prime contender for using match templates instead of the "pseudo function" named templates, e.g. your code above could look like something this, thus eliminating the need for prefixing with $node all the time - and you'd only need to adjust a little in the rest of your code as well (i.e., using apply-templates instead of call-template):
<xsl:template match="*[@isDoc]">
<xsl:variable name="subPages" select="*[@isDoc][not(umbracoNaviHide = 1)]" />
<a href="{umb:NiceUrl(@id)}">
<!-- If there are sub pages, override href -->
<xsl:if test="$subPages"><xsl:attribute name="href">javascript:void(0)</xsl:attribute></xsl:if>
<!-- If this is an ExternalLink document, override href -->
<xsl:if test="self::ExternalLink"><xsl:attribute name="href"><xsl:value-of select="url" /></xsl:attribute></xsl:if>
<span>
<!-- Use pageTitle but fallback to @nodeName if empty -->
<xsl:value-of select="(@nodeName[not(normalize-space(../pageTitle))] | pageTitle)[1]" />
</span>
</a>
</xsl:template>
I wanted only the top root nodes, the ones on the tab navigation to be checked on this test for child nodes. If they have children they should not get a link assigned to them as parents, but I want all subsuquent parents that have children to have links. Is that clearer?
I am new to Umbraco and xslt here is the rest of my navigation code, I will look into your suggestions. Could you look at the whole piece of code below and give me some ideas of how to accomplish my navigation goals. Thanks for all your time!
Using your example of the nav, here is what's needed:
Home (no link applied because page 1,2,3 and 4 are children of Home if Home had NO children then I need it to have a href applied) -Page1 (link) -Page2 (link applied) --Sub2.1 (link applied) --Sub2.2 (link applied) -Page3 (link applied) --Sub3.1(link applied) ---Gran3.1.1 (link applied) -Page4 (link applied)
All "link applied" could be either a link to another page or an "ExternalLink" so that has to be in the choose statement.
Navigation Question
I am am trying to create a "tab" type navigation that will have dropdown links appear on hover, but the top node shouldn't have a link associated with it if it has child nodes (eg; https://edit-www.rose-hulman.edu/offices-services/alumni-affairs-2.aspx). I am using this in my xslt file for the navigation, but as it is if there are grandchild nodes in the navigation that are not "hidden from navigation" then my xslt restricts that inner parent node to not have a link associated with it. Basicly, I don't wan't top level parent nodes to have links associated with them unless they have no subnodes, but I want the ability to have subnodes that link with child nodes as well.
Here is my xslt file:
<xsl:template name="node-link-with-span">
<xsl:param name="node" />
<xsl:if test="string($node) != ''">
<a>
<xsl:attribute name="href">
<xsl:choose>
<xsl:when test="count($node/* [@isDoc and string(umbracoNaviHide) != '1'])">
<![CDATA[javascript://]]>
</xsl:when>
<xsl:when test="$node[name() = 'ExternalLink']">
<xsl:value-of select="$node/url" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="umbraco.library:NiceUrl($node/@id)" />
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<span>
<xsl:call-template name="node-name">
<xsl:with-param name="node" select="$node" />
</xsl:call-template>
</span>
</a>
</xsl:if>
</xsl:template>
<!-- A template to output the correct name for a given node. Better than copy/pasting this code all over the place -->
<xsl:template name="node-name">
<xsl:param name="node" />
<xsl:if test="string($node) != ''">
<xsl:choose>
<xsl:when test="$node/pageTitle != ''">
<xsl:value-of select="$node/pageTitle"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$node/@nodeName"/>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
Hi Steve,
I'm having a hard time understanding exactly what your problem is - I think part of your problem is in another part of the code (not shown), i.e., the code above doesn't recurse through the sub pages...
Say you have the following content structure - what would be your desired HTML output then?
PS: Navigations are a prime contender for using match templates instead of the "pseudo function" named templates, e.g. your code above could look like something this, thus eliminating the need for prefixing with $node all the time - and you'd only need to adjust a little in the rest of your code as well (i.e., using apply-templates instead of call-template):
/Chriztian
Sorry Chriztian,
Here is a link to the page with the navigation: https://edit-www.rose-hulman.edu/offices-services/alumni-affairs-2.aspx
I wanted only the top root nodes, the ones on the tab navigation to be checked on this test for child nodes. If they have children they should not get a link assigned to them as parents, but I want all subsuquent parents that have children to have links. Is that clearer?
I am new to Umbraco and xslt here is the rest of my navigation code, I will look into your suggestions. Could you look at the whole piece of code below and give me some ideas of how to accomplish my navigation goals. Thanks for all your time!
<?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="/">
<xsl:variable name="home" select="$currentPage/ancestor-or-self::Category2HomePage" />
<xsl:variable name="nav" select="$home/*[@isDoc and string(umbracoNaviHide)!='1']" />
<ul>
<xsl:if test="string($home/useAlternateNavigation) = '1'">
<xsl:attribute name="class">alt-nav</xsl:attribute>
</xsl:if>
<xsl:for-each select="$nav">
<li>
<!-- this craziness allows IE to lay subnavs on top of top nav elements if they break onto two lines -->
<xsl:attribute name="style">z-index:<xsl:value-of select="count($nav)-position()+1" />;</xsl:attribute>
<xsl:attribute name="class">
<xsl:if test="$currentPage/ancestor-or-self::*[@isDoc and name()!='Category2HomePage' and @id=current()/@id]">
<xsl:text>active</xsl:text>
</xsl:if>
<xsl:text> </xsl:text>
<xsl:if test="count($nav)=position()">
<xsl:text>last</xsl:text>
</xsl:if>
</xsl:attribute>
<xsl:call-template name="node-link-with-span">
<xsl:with-param name="node" select="current()" />
</xsl:call-template>
<xsl:variable name="subnodes" select="* [@isDoc and string(umbracoNaviHide)!='1']" />
<xsl:if test="$subnodes">
<ul>
<xsl:for-each select="$subnodes">
<li>
<xsl:if test="position()=1">
<xsl:attribute name="class">first</xsl:attribute>
</xsl:if>
<xsl:call-template name="node-link-with-span">
<xsl:with-param name="node" select="current()" />
</xsl:call-template>
</li>
</xsl:for-each>
</ul>
</xsl:if>
</li>
</xsl:for-each>
</ul>
<xsl:if test="string($home/useAlternateNavigation) != '1'">
<img src="/static/phase2/tabNavBorderBottom.jpg" class="tabBorder" />
</xsl:if>
</xsl:template>
<xsl:template name="node-link-with-span">
<xsl:param name="node" />
<xsl:if test="string($node) != ''">
<a>
<xsl:attribute name="href">
<xsl:choose>
<xsl:when test="count($node/* [@isDoc and string(umbracoNaviHide) != '1'])">
<![CDATA[javascript://]]>
</xsl:when>
<xsl:when test="$node[name() = 'ExternalLink']">
<xsl:value-of select="$node/url" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="umbraco.library:NiceUrl($node/@id)" />
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<span>
<xsl:call-template name="node-name">
<xsl:with-param name="node" select="$node" />
</xsl:call-template>
</span>
</a>
</xsl:if>
</xsl:template>
<!-- A template to output the correct name for a given node. Better than copy/pasting this code all over the place -->
<xsl:template name="node-name">
<xsl:param name="node" />
<xsl:if test="string($node) != ''">
<xsl:choose>
<xsl:when test="$node/pageTitle != ''">
<xsl:value-of select="$node/pageTitle"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$node/@nodeName"/>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Using your example of the nav, here is what's needed:
All "link applied" could be either a link to another page or an "ExternalLink" so that has to be in the choose statement.
is working on a reply...