Copied to clipboard

Flag this post as spam?

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


  • Steve 472 posts 1216 karma points
    Aug 08, 2012 @ 22:52
    Steve
    0

    I am new to Umbraco and have templates with navigation that is a set of top level tabs with sub nav dropdown items under each tab. The problem is I need the ability to chose wheather or not the top level tab navigation links to a page or not. All tabs with drop down sub navs don't need to link to anything. I don't know where I would address this? Template, Macro, Doctype? Help please.

  • Dan 1285 posts 3917 karma points c-trib
    Aug 08, 2012 @ 23:23
    Dan
    0

    Hi Steve,

    You would address this in your macro.  It depends on whether you're using XSLT or razor as to exactly how, but the logic would be: iterate through top level nodes; if there are child pages don't add a link element to the current node in the loop; if there aren't child nodes then do add a link element to the current node in the loop.  I tend to prefer XSLT but the code should be fairly simple in either XSLT or razor.

    If you're struggling with the macro syntax post here what you have so far and someone will point you in the right direction.

  • Steve 472 posts 1216 karma points
    Aug 09, 2012 @ 14:27
    Steve
    0

    Thanks Dan,

    Here is the code I am using for my tabed navigation. Would my solution be as simple a changing the axes wherever it refrences this:

    <xsl:variable name="home" select="$currentPage/ancestor-or-self::Category2HomePage" /> 

    To:

    <xsl:variable name="home" select="$currentPage/ancestor::Category2HomePage" />

    ? Let me know if I am missing somthing else. Thanks again!

     

    MY XSLT NAVIGATION:

    <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>

  • Dan 1285 posts 3917 karma points c-trib
    Aug 09, 2012 @ 14:45
    Dan
    0

    Hi,

    I'm not sure what your 'node-link-with-span' template is doing, but you could rearrange the middle bit of the code to declare your 'subnodes' variable then set an href property on the link if there are subnodes like this (I've removed your call to the template to render the link and replaced it with an anchor tag, just to demonstrate):

    <xsl:variable name="subnodes" select="* [@isDoc and string(umbracoNaviHide)!='1']" />
    <a>
        <xsl:if test="$subnodes">
            <xsl:attribute name="href">
                <xsl:value-of select="umbraco.library:NiceUrl(@id)" />
            </xsl:attribute>
        </xsl:if>
    </a>

    You can obviously do that logic within your template, passing $subnodes to it (or even a 'count($subnodes)') but hopefully you get the idea...

  • Steve 472 posts 1216 karma points
    Aug 10, 2012 @ 22:42
    Steve
    0

    Dan,

    Here are the templates that are called in the tab navigation. I believe I would have to change the template "node-link-with-span" to achieve the correct effect, but I am having some difficulty with the xsl:when and xsl:otherwise logic. If there are child nodes then I don't want a href applied to the parent node.

    <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="$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>

  • Jon Dunfee 199 posts 468 karma points
    Aug 11, 2012 @ 21:45
    Jon Dunfee
    0

    At first I was thinking you could just add another case to your choose statement:

            <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>

    But if you don't want the anchor altogether I think you could do the following:

      <xsl:template name="node-link-with-span">
        <xsl:param name="node" />  
        <xsl:choose>
          <xsl:when test="string($node) = ''"><!-- skip --></xsl:when>
          <xsl:when test="count($node/* [@isDoc and string(umbracoNaviHide) != '1'])">
              <span>
                <xsl:call-template name="node-name">
                  <xsl:with-param name="node" select="$node" />
                </xsl:call-template>
              </span>        
          </xsl:when>
          <xsl:when test="$node[name() = 'ExternalLink']">
            <a>
              <xsl:attribute name="href">
                <xsl:choose>
                  <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:when>
          <xsl:otherwise />
        </xsl:choose>
      </xsl:template>

  • Steve 472 posts 1216 karma points
    Aug 13, 2012 @ 16:37
    Steve
    0

    Jon,

    Thanks for your suggestions.  The first one, I believe would be the correct approch, but as it is only removes the href on the parent for the first page. After any other clicks to child node pages the parent href for the navs with children has an active href when it shouldn't. Any suggestions ?

  • Jon Dunfee 199 posts 468 karma points
    Aug 13, 2012 @ 17:17
    Jon Dunfee
    0

    The first example doesn't remove the href, it populates it with href="javascript://" which essentially does nothing but preserve any styling you may have that follows a markup pattern.  You are right, it may inherit active styling because it's not associated with a page or anchor.

    I typically set a blanket styling for nav links and set a class name for the branch I'm on so I have control over the appearance.  Here's an example of XSLT I use:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]>
    <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="html" omit-xml-declaration="yes" />

    <xsl:param name="currentPage"/>

    <xsl:variable name="maxLevel"><xsl:choose>
      <xsl:when test="macro/maxLevel != ''"><xsl:value-of select="macro/maxLevel" /></xsl:when>
      <xsl:otherwise>2</xsl:otherwise></xsl:choose></xsl:variable>
        
    <xsl:template match="/">
      <ul class="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:for-each select="$parent/* [@isDoc and string(umbracoNaviHide) != '1' and @level &lt;= $maxLevel]">
        <li>
          <xsl:attribute name="class">nav-item nav-item-<xsl:value-of select="position()" /></xsl:attribute>
          <a>
            <xsl:attribute name="href">
              <xsl:choose>
                <xsl:when test="./externalRedirectURL != ''">
                  <xsl:value-of select="./externalRedirectURL" />
                </xsl:when>
                <xsl:otherwise>
                  <xsl:value-of select="umbraco.library:NiceUrl(@id)" />
                </xsl:otherwise>
              </xsl:choose>
            </xsl:attribute>        
            <xsl:if test="string(./topNavNewWindow) = '1'">
              <xsl:attribute name="target">_blank</xsl:attribute>
            </xsl:if>        
            <xsl:if test="$currentPage/ancestor-or-self::* [@isDoc and @id = current()/@id]">
              <xsl:attribute name="class">on</xsl:attribute>
              <xsl:attribute name="rel">nofollow</xsl:attribute>
            </xsl:if>
            <xsl:choose>
              <xsl:when test="./topNavText != ''">
                <xsl:value-of select="./topNavText" />
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="@nodeName"/>
              </xsl:otherwise>
            </xsl:choose>
          </a>
          <xsl:if test="count(./* [@isDoc and string(umbracoNaviHide) != '1' and @level &lt;= $maxLevel])">
            <ul>
              <xsl:call-template name="drawNodes">    
                <xsl:with-param name="parent" select="."/>
              </xsl:call-template>  
            </ul>
          </xsl:if>
        </li>
      </xsl:for-each>
    </xsl:template>
    </xsl:stylesheet>

    And a snippet of styling I may have:

    ul.nav margin:0padding0text-align:center}
    ul.nav li 
      display:inline-block
      position:relative
      padding-top:1px
      margin:0;
    }
    .lt-ie9 ul.nav li display:inline}

    ul.nav li {
      display:block
      color:#fff
      text-decoration:none
      text-transform:uppercase
      padding:15px
    }
    .lt-ie9 ul.nav li display:inline}

    ul.nav li a.on text-decoration:underline}
    ul.nav li:hover background#ccc}
    ul.nav li:hover ul display:block}
    ul.nav ul {
      display:none;
      position:absolute;
      z-index:99999;
      top:23px;
      left:-3px
      width:165px;
    }
    ul.nav ul li {
      clear:left;
      float:none;
      background#fff;
      width:165px;
      padding:0;
      margin:0;
    }
    ul.nav ul li {
      color:#000;
      text-align:center;
      text-decoration:none;
      text-transform:none;
      display:block;
      width:165px;
      heightauto;
      background:#fff;
      border-topnone;
      border-rightnone;
      border-bottom1px solid #ccc;
      clearleft;
      padding4px 4px;
      margin:0;
    }
    ul.nav ul li a:hover {
      background#ccc;
      color#000;
      text-decorationnone;
    }

     

  • Steve 472 posts 1216 karma points
    Aug 21, 2012 @ 19:20
    Steve
    0

    Thanks for your help works great!! I appreciate your time!

  • Steve 472 posts 1216 karma points
    Aug 27, 2012 @ 20:39
    Steve
    0

    One more question :)

    How could I alter your xslt to allow for child nodes to have links if they had granchildren? As it is now adding grandchildren makes the parent node receive the "javascript://" link.

  • Jon Dunfee 199 posts 468 karma points
    Sep 04, 2012 @ 21:09
    Jon Dunfee
    100

    You may need to get the crayons out and sketch it out for me.

    This what you are desiring? (non-linked represent anchors with href="javascript://")

    TAB TAB TAB
    Child Child
    Grandchild

    However, the tidbit of XSLT you are using is doing this?

    TAB TAB TAB
    Child Child
    Grandchild

    So, if I'm following correctly, you may just need to update your case with a level expression, so something like this:

      <a>
        <xsl:attribute name="href">
          <xsl:choose>
            <xsl:when test="count($node/* [@isDoc and string(umbracoNaviHide) != '1']) and $node/@level <= 2">
              <![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>  

  • Steve 472 posts 1216 karma points
    Apr 25, 2014 @ 19:56
    Steve
    0

    Thanks John. I'ts been so long since I has asked this question I don't know wheather or not I had figured this out or not. I might have even just re-wrote it as a Razor script. From what I understand about xslt now, it appears that your idea is the answer to my last question though. ;)

Please Sign in or register to post replies

Write your reply to:

Draft