I am making a navigation which involves some quite intensive CSS joggling, so basically what I would like to achieve is adding classes to the <li> elements based on different things.
Now I have classes for: first, last and selected and any combination of these. What I would also like is to get classes added for "selected - 1" and "selected + 1" in order to style the menu-tabs on either side of the selected tab.
I would imagine first you have your menu in a xsl:for-each tag so you can loop through each menu node, while in a for-each you have access to the "position()" of a node, this is a standard function not specific to any kind of xml node, but as you can imagine it allows you to get the position in a node-set of a found node.
A practical use would be as such:
<xsl:for-each select="$menuNodes"> <!-- using a variable here to make the markup below clearer, this will contain the value of the class --> <!-- the first line adds the "first" class --> <!-- the second line adds the "last" class --> <!-- the third line adds the "selected" class, this logic is very basic if the currentPage id is the same as the current menu node id then we have a winner :)-->
<xsl:variable name="classValue"> <xsl:if test="position() = 1">first </xsl:if> <xsl:if test="position() = last()">last </xsl:if> <xsl:if text="$currentPage/@id = ./@id">selected</xsl:if> </xsl:variable> <li> <!-- only add a class attribute if we have anything to show from the variable above, cleaner HTML code, yay... --> <xsl:if test="string-length($classValue) > 0"> <xsl:attribute name="class"><xsl:value-of select="$classValue" /></xsl:attribute> </xsl:if> <!-- whatever you want to display in your li tag goes here --> </li> </xsl:for-each>
You can combine the above ideas in the logic in the classValue to get the kind of class name you're looking for, I hope this helped you find your solution (if so mark it :) ).
Jamies answer is spot on, but I noticed it didn't contain the selected - 1 / selected + 1 functionality you asked for, so I've expanded his solution to accomodate this.
Below you'll find an xslt-file ready to use with the runway example, in the homepage template and second level textpages:
Thanks Jamie for the answer, but as Jesper said I already had that covered :)
Now you both seem to be going out from the same navigation template am I right? E.g. the variable $menuNodes is used to iterate. Now the template I wa using (which is the one that came with the Runway navigation module) does not store the nodes in a variable, it just selects them directly in the for-each statement. Can I find the template you are basing your code on somewhere? Because when I try to "decode" some the first post by Jesper, I don't get into the for-each loop.
From what I can see in the post, this is declared prior to the for-each loop:
Help needed for advanced XSLT navigation
Hello
I am making a navigation which involves some quite intensive CSS joggling, so basically what I would like to achieve is adding classes to the <li> elements based on different things.
Now I have classes for: first, last and selected and any combination of these. What I would also like is to get classes added for "selected - 1" and "selected + 1" in order to style the menu-tabs on either side of the selected tab.
So a menu could look like this:
<ul>
<li class="first">....</li>
<li>...</li>
<li class="next_selected">...</li>
<li class="selected last">....</li>
</ul>
or like this:
I would imagine first you have your menu in a xsl:for-each tag so you can loop through each menu node, while in a for-each you have access to the "position()" of a node, this is a standard function not specific to any kind of xml node, but as you can imagine it allows you to get the position in a node-set of a found node.
A practical use would be as such:
You can combine the above ideas in the logic in the classValue to get the kind of class name you're looking for, I hope this helped you find your solution (if so mark it :) ).
Jamies answer is spot on, but I noticed it didn't contain the selected - 1 / selected + 1 functionality you asked for, so I've expanded his solution to accomodate this.
Below you'll find an xslt-file ready to use with the runway example, in the homepage template and second level textpages:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]> <xsl:stylesheet <span style="white-space: pre;"> </span>version="1.0" <span style="white-space: pre;"> </span>xmlns:xsl="http://www.w3.org/1999/XSL/Transform" <span style="white-space: pre;"> </span>xmlns:msxml="urn:schemas-microsoft-com:xslt" <span style="white-space: pre;"> </span>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" <span style="white-space: pre;"> </span>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:variable name="menuNodes" select="$currentPage/ancestor-or-self::node[@nodeTypeAlias='RunwayHomepage']/node[./data[@alias='umbracoNaviHide'] = '0']" /> <xsl:template match="/"> <span style="white-space: pre;"> </span><ul> <span style="white-space: pre;"> </span><xsl:for-each select="$menuNodes"> <span style="white-space: pre;"> </span> <xsl:variable name="currPos" select="position()" /> <span style="white-space: pre;"> </span> <xsl:variable name="classValue"> <span style="white-space: pre;"> </span> <xsl:if test="position() = 1">first </xsl:if> <span style="white-space: pre;"> </span> <xsl:if test="position() = last()">last </xsl:if> <span style="white-space: pre;"> </span> <xsl:if test="$currentPage/@id = ./@id">selected</xsl:if> <span style="white-space: pre;"> </span><!-- Next two lines implements befor and after selected item classes --> <span style="white-space: pre;"> </span> <xsl:if test="$menuNodes[number($currPos)+1]/@id = $currentPage/@id">beforeSelected</xsl:if> <span style="white-space: pre;"> </span> <xsl:if test="$menuNodes[number($currPos)-1]/@id = $currentPage/@id">afterSelected</xsl:if> <span style="white-space: pre;"> </span> </xsl:variable> <span style="white-space: pre;"> </span> <li> <span style="white-space: pre;"> </span><xsl:if test="string-length($classValue) > 0"> <span style="white-space: pre;"> </span><xsl:attribute name="class"><xsl:value-of select="$classValue" /></xsl:attribute> <span style="white-space: pre;"> </span></xsl:if> <span style="white-space: pre;"> </span><a href="{umbraco.library:NiceUrl(@id)}"> <span style="white-space: pre;"> </span><xsl:value-of select="$classValue" /> : <xsl:value-of select="@nodeName" /> <span style="white-space: pre;"> </span> <span style="white-space: pre;"> </span></li> <span style="white-space: pre;"> </span></xsl:for-each> <span style="white-space: pre;"> </span></ul> </xsl:template> </xsl:stylesheet>Regards
.Hauge
Once again burned by the editor in this forum
Seems only way to get code properly into the forum is if you type it in by hand:
Short version:
To add before and after classe youll need three more lines of xsl in the classValue variable:
Outside the classValue variable You'll need a variable that stores the current position.
Inside the classValue you'll need two more lines
They basically look at the next or the previous node in $menuNodes and checks if next or previous node is the current page node.
Regards
.Hauge
Thanks Jamie for the answer, but as Jesper said I already had that covered :)
Now you both seem to be going out from the same navigation template am I right? E.g. the variable $menuNodes is used to iterate. Now the template I wa using (which is the one that came with the Runway navigation module) does not store the nodes in a variable, it just selects them directly in the for-each statement. Can I find the template you are basing your code on somewhere? Because when I try to "decode" some the first post by Jesper, I don't get into the for-each loop.
From what I can see in the post, this is declared prior to the for-each loop:
Hi Thomas
You're right; there is something missing: A variable right after the currentPage param, it looks like this:
I actually tested the xslt from my first post on a runway site, drop me a mail on jesper {at} jm-net {dot} dk, and I'll send you the file.
.Hauge
Hurray, it works great!
Now on to finding out why it won't include my own document types..
is working on a reply...
This forum is in read-only mode while we transition to the new forum.
You can continue this topic on the new forum by tapping the "Continue discussion" link below.