Copied to clipboard

Flag this post as spam?

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


  • Dwayne A 97 posts 117 karma points
    Apr 01, 2011 @ 10:48
    Dwayne A
    0

    Tree navigation styling

    I've created a tree navigation, which worked perfectly for my needs until some bonehead user got the bright idea to create three tiers of navigation. : - ) Oh, the demands. Now my XSLT is inadequate. I've tinkered with it, but am still unable to sort out how to structure my templates. I'm close to a solution, but do not believe it is the most eloquent method and still is not as I want it. Ideally, it should iterate indefinitely by level, no? Even so, three or four levels should do the trick in this case.

    Specs
    1. The navigation should allow for indentation of each url by level. That works so far. See image below.
    2. It should allow for style changes e.g. color, hover and background of the selected page and it's parent page(s) ONLY. The selected page in the image is test 02, yet my xslt allows all siblings on the same level to be selected, i.e. test 1 AND test 02

        <xsl:template match="/">
          <xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::* [@level=1]" />
            <xsl:variable name="mainMenuItems" select="$siteRoot /*[@isDoc and string(umbracoNaviHide) != '1']" />
              <ul class="nav" id="nav-level1">
                <xsl:apply-templates select="$mainMenuItems" />
              </ul>
        </xsl:template>

        <xsl:template name="ShowMenuItem" match="*">
          <xsl:variable name="isCurrent" select="@id = $currentPage/ancestor-or-self::* /@id" />
          <li style="background:#f1f1f1;">
              <xsl:if test="$isCurrent">
                <xsl:attribute name="class">
                  <xsl:text>current</xsl:text>
                </xsl:attribute>
                </xsl:if>
                <a href="{umbraco.library:NiceUrl(@id)}">
                    <xsl:value-of select="@nodeName"/>
                </a>
              <xsl:variable name="subPages" select="./ *[@isDoc and string(umbracoNaviHide) != '1']" />
                <xsl:if test="$isCurrent and $subPages">
                  <ul class="nav" id="nav-level2" style="padding-left:10px;">
                    <xsl:apply-templates select="$subPages" />
                  </ul>
              </xsl:if>
            </li>
          </xsl:template>

    All suggestions welcome and appreciated.

  • Michael Latouche 504 posts 819 karma points MVP 3x c-trib
    Apr 01, 2011 @ 11:54
    Michael Latouche
    0

    Hi Dwayne,

    I think the problem is that your test

    <xsl:variable name="isCurrent" select="@id = $currentPage/ancestor-or-self::* /@id" />

    Will retuen true for "cousins" also. See this post related to a similar problem: http://our.umbraco.org/forum/developers/xslt/18434-Syntax-question-ancestor-or-self-but-not-%27cousins%27

    From what I read there, I think changing your test to someting like

    <xsl:variable name="isCurrent" select="@id = $currentPage/ancestor-or-self::* [@id=$currentPage/@id or umbraco.library:GetXmlNodeById(@id)/@level &lt; $currentPage/@level] /@id" />

    I am not an XSLT expert so there might be a cleaner way, but I hope this helps you.

    Cheers,

    Michael.


  • Dwayne A 97 posts 117 karma points
    Apr 01, 2011 @ 12:32
    Dwayne A
    0

    Hey Michael,

    I've looked at it the thread you mention, but it appears uncertain they arrived at a valid solution. I tried to toy with it, but still no luck. Not at all certain what they are addressing there with "Site/Link". A very different approach than I want to go with. It seems hardwired to me and I like flexibility.

    You are most certainly correct that the select statement needs tweaking, but wouldn't it be the latter, which tests level 2 URLs?

    <xsl:variable name="subPages" select="./ *[@isDoc and string(umbracoNaviHide) != '1']" />
    <xsl:if test="$isCurrent and $subPages">
  • Dwayne A 97 posts 117 karma points
    Apr 01, 2011 @ 12:53
    Dwayne A
    0

    Have tried. Same results as before.

        <xsl:template match="/">
          <xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::* [@level=1]" />
            <xsl:variable name="mainMenuItems" select="$siteRoot /*[@isDoc and string(umbracoNaviHide) != '1']" />
              <ul class="nav" id="nav-level1">
                <xsl:apply-templates select="$mainMenuItems" />
              </ul>
        </xsl:template>

        <xsl:template name="ShowMenuItem" match="*">
          <xsl:variable name="isCurrent" select="@id = $currentPage/ancestor-or-self::* [@id=$currentPage/@id or umbraco.library:GetXmlNodeById(@id)/@level &lt; $currentPage/@level] /@id" />
          <li style="background:#f1f1f1;">
              <xsl:if test="$isCurrent">
                <xsl:attribute name="class">
                  <xsl:text>current</xsl:text>
                </xsl:attribute>
                </xsl:if>
                <a href="{umbraco.library:NiceUrl(@id)}">
                    <xsl:value-of select="@nodeName"/>
                </a>
              <xsl:variable name="subPages" select="./ *[@isDoc and umbraco.library:GetXmlNodeById(@parentID)/@level &lt; $currentPage/@level]" />
                <xsl:if test="$isCurrent and $subPages">
                  <ul class="nav" id="nav-level2" style="padding-left:10px;">
                    <xsl:apply-templates select="$subPages" />
                  </ul>
              </xsl:if>
            </li>
          </xsl:template>
    </xsl:stylesheet>
  • Dwayne A 97 posts 117 karma points
    Apr 01, 2011 @ 12:58
    Dwayne A
    0

    By the way. I'm controlling styles with

    <xsl:attribute name="class">
     <xsl:text>current</xsl:text>
    </xsl:attribute>

    The class .current sets the selected pages <a> styles.

  • Michael Latouche 504 posts 819 karma points MVP 3x c-trib
    Apr 01, 2011 @ 13:10
    Michael Latouche
    0

    Hi Dwayne,

    The post I mentioned was indeed not a perfect match, but I thought the test on the level like I proposed would work. Apparently not, damn ;-)

    I may be wrong but I don't think the problem resides in the subPages. I think it comes from the fact that the ancestor-or-self statement, as it is writen, gets cousins of the last level as well.

    Anyway, another option would be to add an extra check on the place where you test if you need to use the "current" class or not. Could you maybe try with this:

    <xsl:template match="/">
          <xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::* [@level=1]" />
            <xsl:variable name="mainMenuItems" select="$siteRoot /*[@isDoc and string(umbracoNaviHide) != '1']" />
              <ul class="nav" id="nav-level1">
                <xsl:apply-templates select="$mainMenuItems" />
              </ul>
        </xsl:template>

        <xsl:template name="ShowMenuItem" match="*">
          <xsl:variable name="isCurrent" select="@id = $currentPage/ancestor-or-self::* /@id" />
          <li style="background:#f1f1f1;">
              <xsl:if test="$isCurrent and (@id = $currentPage/@id or @level &lt; $currentPage/@level)">
                <xsl:attribute name="class">
                  <xsl:text>current</xsl:text>
                </xsl:attribute>
                </xsl:if>
                <a href="{umbraco.library:NiceUrl(@id)}">
                    <xsl:value-of select="@nodeName"/>
                </a>
              <xsl:variable name="subPages" select="./ *[@isDoc and string(umbracoNaviHide) != '1']" />
                <xsl:if test="$isCurrent and $subPages">
                  <ul class="nav" id="nav-level2" style="padding-left:10px;">
                    <xsl:apply-templates select="$subPages" />
                  </ul>
              </xsl:if>
            </li>
          </xsl:template>

    I have put my code change in bold, hope it will remain visible with the formatting...

    Hope this one wil work :-)

    Cheers,

    Michael.

  • Dwayne A 97 posts 117 karma points
    Apr 01, 2011 @ 13:39
    Dwayne A
    0

    Michael, same results, different method ;-) I see where you are going. Odd that it differentiates level 1 and 2 elements from their respective cousins, but when it comes to level three it does not. Could this have any thing to do with the fact there is a style id for 1 and 2 but stops there? That was my initial thinking.

    However, the styles seem to apply to level three in most cases, just not thye selected color attribute.

  • Dwayne A 97 posts 117 karma points
    Apr 01, 2011 @ 13:50
    Dwayne A
    0

    We seem to be on the right track. Changed

    <xsl:if test="$isCurrent and (@id = $currentPage/@id or @level &lt; $currentPage/@level)">

    to

    <xsl:if test="$isCurrent and (@id = $currentPage/@id)">

    and get

  • Michael Latouche 504 posts 819 karma points MVP 3x c-trib
    Apr 01, 2011 @ 14:33
    Michael Latouche
    0

    Hi Dwayne,

    I don't think it has to do with the style-id's that stop at level2, because as far as I understand, it is the attribute "class=current" that gets wrongly set on the "cousin" nodes.

    The result you get with your last example is indeed a good sign, it actually conforts me in thinking that the issue is only on the value of  $isCurrent, but I must say I don't understand why my proposition with the extra check on levels did not do the trick :-s Because there we should actually exclude nodes on the same level as the currentpage, aka the cousins. Maybe for some reason the "@level" is not available? Maybe you could try to retrieve it explicitely then:

    <xsl:if test="$isCurrent and (@id = $currentPage/@id or umbraco.library:GetXmlNodeById(@id)/@level &lt; $currentPage/@level)">

    Let's hope ;-)

    Cheers,

    Michael.

     

  • Dwayne A 97 posts 117 karma points
    Apr 01, 2011 @ 14:37
    Dwayne A
    0

    Thanks. I'll try that. Meanwhile, I am looking here at a tree navi solution to see how it was constructed. maybe something here can help.

    http://our.umbraco.org/forum/developers/xslt/9894-creating-an-expandable-tree-using-XSLT

  • Dwayne A 97 posts 117 karma points
    Apr 01, 2011 @ 14:43
    Dwayne A
    0

    Michael, wish I could say that worked, but no dice. It sounds reasonable, what you said just before. It seems for some reason all is well on levels 1 and 2, but at level 3 all nodes on that level become current.

  • Michael Latouche 504 posts 819 karma points MVP 3x c-trib
    Apr 01, 2011 @ 14:55
    Michael Latouche
    0

    Mmmhhh, very strange indeed :-(

    Maybe it is time for some debugging. Maybe at the end of your test on $isCurrent, after you have added the class attribute, you could output the @id, @level, $currentPage/@id and $currentPage/@level.

    This might help us understand what is actually happening and why he keeps highlighting cousins.

    Cheers,

    Michael.

  • Dwayne A 97 posts 117 karma points
    Apr 01, 2011 @ 14:59
    Dwayne A
    0

    Yeah, sounds reasonable.

Please Sign in or register to post replies

Write your reply to:

Draft